Merged changes in the trunk up to revision 51718.
[blender.git] / build_files / scons / tools / Blender.py
1 #!/usr/bin/env python
2
3 """
4 tools.BlenderEnvironment
5
6 This environment builds on SCons.Script.SConscript.SConsEnvironment
7
8 * library repository
9 * custom printout
10 * wrapper functions
11
12 TODO: clean up and sanitise code - crosscheck with btools and SConstruct
13 to kill any code duplication
14
15 """
16
17 import os
18 import os.path
19 import string
20 import glob
21 import time
22 import sys
23 import tarfile
24 import shutil
25 import cStringIO
26 import platform
27
28 from SCons.Script.SConscript import SConsEnvironment
29 import SCons.Action
30 import SCons.Util
31 import SCons.Builder
32 import SCons.Tool
33 import bcolors
34 bc = bcolors.bcolors()
35 import btools
36 VERSION = btools.VERSION
37 VERSION_RELEASE_CYCLE = btools.VERSION_RELEASE_CYCLE
38
39 Split = SCons.Util.Split
40 Action = SCons.Action.Action
41 Builder = SCons.Builder.Builder
42 GetBuildPath = SConsEnvironment.GetBuildPath
43
44 # a few globals
45 root_build_dir = ''
46 doc_build_dir = ''
47 quickie = None # Anything else than None if BF_QUICK has been passed
48 quicklist = [] # The list of libraries/programs to compile during a quickie
49 program_list = [] # A list holding Nodes to final binaries, used to create installs
50 arguments = None
51 targets = None
52 resources = []
53 bitness = 0
54
55 #some internals
56 blenderdeps = [] # don't manipulate this one outside this module!
57
58 ##### LIB STUFF ##########
59
60 possible_types = ['core'] # can be set in ie. SConstruct
61 libs = {}
62 vcp = []
63
64 def getresources():
65     return resources
66
67 def init_lib_dict():
68     for pt in possible_types:
69         libs[pt] = {}
70
71 # helper func for add_lib_to_dict
72 def internal_lib_to_dict(dict = None, libtype = None, libname = None, priority = 100):
73     if not libname in dict[libtype]:
74         done = None
75         while not done:
76             if dict[libtype].has_key(priority):
77                 priority = priority + 1
78             else:
79                 done = True
80         dict[libtype][priority] = libname
81
82 # libtype and priority can both be lists, for defining lib in multiple places
83 def add_lib_to_dict(env, dict = None, libtype = None, libname = None, priority = 100):
84     if not dict or not libtype or not libname:
85         print "Passed wrong arg"
86         env.Exit()
87
88     if type(libtype) is str and type(priority) is int:
89         internal_lib_to_dict(dict, libtype, libname, priority)
90     elif type(libtype) is list and type(priority) is list:
91         if len(libtype)==len(priority):
92             for lt, p in zip(libtype, priority):
93                 internal_lib_to_dict(dict, lt, libname, p)
94         else:
95             print "libtype and priority lists are unequal in length"
96             env.Exit()
97     else:
98         print "Wrong type combinations for libtype and priority. Only str and int or list and list"
99         env.Exit()
100
101 def create_blender_liblist(lenv = None, libtype = None):
102     if not lenv or not libtype:
103         print "missing arg"
104
105     lst = []
106     if libtype in possible_types:
107         curlib = libs[libtype]
108         sortlist = curlib.keys()
109         sortlist.sort()
110         for sk in sortlist:
111             v = curlib[sk]
112             if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
113                 target = os.path.abspath(os.getcwd() + os.sep + root_build_dir + 'lib' + os.sep +lenv['LIBPREFIX'] + v + lenv['LIBSUFFIX'])
114             else:
115                 target = os.path.abspath(root_build_dir + 'lib' + os.sep +lenv['LIBPREFIX'] + v + lenv['LIBSUFFIX'])
116             lst.append(target)
117
118     return lst
119
120 ## TODO: static linking
121 def setup_staticlibs(lenv):
122     statlibs = [
123         #here libs for static linking
124     ]
125
126     libincs = []
127
128     if lenv['WITH_BF_FFMPEG']:
129         libincs += Split(lenv['BF_FFMPEG_LIBPATH'])
130
131     libincs.extend([
132         lenv['BF_OPENGL_LIBPATH'],
133         lenv['BF_JPEG_LIBPATH'],
134         lenv['BF_ZLIB_LIBPATH'],
135         lenv['BF_PNG_LIBPATH'],
136         lenv['BF_ICONV_LIBPATH']
137         ])
138
139     if lenv['WITH_BF_STATICJPEG']:
140         statlibs += Split(lenv['BF_JPEG_LIB_STATIC'])
141     if lenv['WITH_BF_STATICPNG']:
142         statlibs += Split(lenv['BF_PNG_LIB_STATIC'])
143
144     libincs += Split(lenv['BF_FREETYPE_LIBPATH'])
145     if lenv['WITH_BF_PYTHON']:
146         libincs += Split(lenv['BF_PYTHON_LIBPATH'])
147     if lenv['WITH_BF_SDL']:
148         libincs += Split(lenv['BF_SDL_LIBPATH'])
149     if lenv['WITH_BF_JACK']:
150         libincs += Split(lenv['BF_JACK_LIBPATH'])
151         if lenv['WITH_BF_STATICJACK']:
152             statlibs += Split(lenv['BF_JACK_LIB_STATIC'])
153     if lenv['WITH_BF_SNDFILE']:
154         libincs += Split(lenv['BF_SNDFILE_LIBPATH'])
155     if lenv['WITH_BF_OPENEXR']:
156         libincs += Split(lenv['BF_OPENEXR_LIBPATH'])
157         if lenv['WITH_BF_STATICOPENEXR']:
158             statlibs += Split(lenv['BF_OPENEXR_LIB_STATIC'])
159     if lenv['WITH_BF_TIFF']:
160         libincs += Split(lenv['BF_TIFF_LIBPATH'])
161         if lenv['WITH_BF_STATICTIFF']:
162             statlibs += Split(lenv['BF_TIFF_LIB_STATIC'])
163     if lenv['WITH_BF_ZLIB'] and lenv['WITH_BF_STATICZLIB']:
164         statlibs += Split(lenv['BF_ZLIB_LIB_STATIC'])
165     if lenv['WITH_BF_FFTW3']:
166         libincs += Split(lenv['BF_FFTW3_LIBPATH'])
167         if lenv['WITH_BF_STATICFFTW3']:
168             statlibs += Split(lenv['BF_FFTW3_LIB_STATIC'])
169     if lenv['WITH_BF_ELTOPO']:
170         libincs += Split(lenv['BF_LAPACK_LIBPATH'])
171         if lenv['WITH_BF_STATICLAPACK']:
172                     statlibs += Split(lenv['BF_LAPACK_LIB_STATIC'])        
173     if lenv['WITH_BF_FFMPEG'] and lenv['WITH_BF_STATICFFMPEG']:
174         statlibs += Split(lenv['BF_FFMPEG_LIB_STATIC'])
175     if lenv['WITH_BF_INTERNATIONAL']:
176         libincs += Split(lenv['BF_GETTEXT_LIBPATH'])
177         if lenv['WITH_BF_GETTEXT_STATIC']:
178             statlibs += Split(lenv['BF_GETTEXT_LIB_STATIC'])
179         if lenv['WITH_BF_FREETYPE_STATIC']:
180             statlibs += Split(lenv['BF_FREETYPE_LIB_STATIC'])
181     if lenv['WITH_BF_OPENAL']:
182         libincs += Split(lenv['BF_OPENAL_LIBPATH'])
183         if lenv['WITH_BF_STATICOPENAL']:
184             statlibs += Split(lenv['BF_OPENAL_LIB_STATIC'])
185     if lenv['WITH_BF_STATICOPENGL']:
186         statlibs += Split(lenv['BF_OPENGL_LIB_STATIC'])
187     if lenv['WITH_BF_STATICCXX']:
188         statlibs += Split(lenv['BF_CXX_LIB_STATIC'])
189
190     if lenv['WITH_BF_PYTHON'] and lenv['WITH_BF_STATICPYTHON']:
191         statlibs += Split(lenv['BF_PYTHON_LIB_STATIC'])
192
193     if lenv['WITH_BF_SNDFILE'] and lenv['WITH_BF_STATICSNDFILE']:
194         statlibs += Split(lenv['BF_SNDFILE_LIB_STATIC'])
195
196     if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
197         libincs += Split(lenv['BF_PTHREADS_LIBPATH'])
198
199     if lenv['WITH_BF_COLLADA']:
200         libincs += Split(lenv['BF_OPENCOLLADA_LIBPATH'])
201         if lenv['OURPLATFORM'] not in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
202             libincs += Split(lenv['BF_PCRE_LIBPATH'])
203             libincs += Split(lenv['BF_EXPAT_LIBPATH'])
204         if lenv['WITH_BF_STATICOPENCOLLADA']:
205             statlibs += Split(lenv['BF_OPENCOLLADA_LIB_STATIC'])
206
207     if lenv['WITH_BF_OPENMP']:
208         if lenv['OURPLATFORM'] == 'linuxcross':
209             libincs += Split(lenv['BF_OPENMP_LIBPATH'])
210         if lenv['WITH_BF_STATICOPENMP']:
211             statlibs += Split(lenv['BF_OPENMP_LIB_STATIC'])
212             
213     if lenv['WITH_BF_OIIO']:
214         libincs += Split(lenv['BF_OIIO_LIBPATH'])
215         if lenv['WITH_BF_STATICOIIO']:
216             statlibs += Split(lenv['BF_OIIO_LIB_STATIC'])
217
218     if lenv['WITH_BF_OCIO']:
219         libincs += Split(lenv['BF_OCIO_LIBPATH'])
220         if lenv['WITH_BF_STATICOCIO']:
221             statlibs += Split(lenv['BF_OCIO_LIB_STATIC'])
222
223     if lenv['WITH_BF_BOOST']:
224         libincs += Split(lenv['BF_BOOST_LIBPATH'])
225         if lenv['WITH_BF_STATICBOOST']:
226             statlibs += Split(lenv['BF_BOOST_LIB_STATIC'])
227
228     # setting this last so any overriding of manually libs could be handled
229     if lenv['OURPLATFORM'] not in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross', 'win64-mingw'):
230         libincs.append('/usr/lib')
231
232     if lenv['WITH_BF_JEMALLOC']:
233         libincs += Split(lenv['BF_JEMALLOC_LIBPATH'])
234         if lenv['WITH_BF_STATICJEMALLOC']:
235             statlibs += Split(lenv['BF_JEMALLOC_LIB_STATIC'])
236
237     if lenv['OURPLATFORM']=='linux':
238         if lenv['WITH_BF_3DMOUSE']:
239             libincs += Split(lenv['BF_3DMOUSE_LIBPATH'])
240             if lenv['WITH_BF_STATIC3DMOUSE']:
241                 statlibs += Split(lenv['BF_3DMOUSE_LIB_STATIC'])
242
243     return statlibs, libincs
244
245 def setup_syslibs(lenv):
246     syslibs = []
247
248     if not lenv['WITH_BF_FREETYPE_STATIC']:
249         syslibs += Split(lenv['BF_FREETYPE_LIB'])
250     if lenv['WITH_BF_PYTHON'] and not lenv['WITH_BF_STATICPYTHON']:
251         if lenv['BF_DEBUG'] and lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc', 'win32-mingw', 'win64-mingw'):
252             syslibs.append(lenv['BF_PYTHON_LIB']+'_d')
253         else:
254             syslibs.append(lenv['BF_PYTHON_LIB'])
255     if lenv['WITH_BF_INTERNATIONAL'] and not lenv['WITH_BF_GETTEXT_STATIC']:
256         syslibs += Split(lenv['BF_GETTEXT_LIB'])
257     if lenv['WITH_BF_OPENAL']:
258         if not lenv['WITH_BF_STATICOPENAL']:
259             syslibs += Split(lenv['BF_OPENAL_LIB'])
260     if lenv['WITH_BF_OPENMP'] and lenv['CC'] != 'icc' and not lenv['WITH_BF_STATICOPENMP']:
261         if lenv['CC'] == 'cl.exe':
262             syslibs += ['vcomp']
263         else:
264             syslibs += ['gomp']
265     if lenv['WITH_BF_ICONV']:
266         syslibs += Split(lenv['BF_ICONV_LIB'])
267     if lenv['WITH_BF_OIIO']:
268         if not lenv['WITH_BF_STATICOIIO']:
269             syslibs += Split(lenv['BF_OIIO_LIB'])
270
271     if lenv['WITH_BF_OCIO']:
272         if not lenv['WITH_BF_STATICOCIO']:
273             syslibs += Split(lenv['BF_OCIO_LIB'])
274
275     if lenv['WITH_BF_OPENEXR'] and not lenv['WITH_BF_STATICOPENEXR']:
276         syslibs += Split(lenv['BF_OPENEXR_LIB'])
277     if lenv['WITH_BF_TIFF'] and not lenv['WITH_BF_STATICTIFF']:
278         syslibs += Split(lenv['BF_TIFF_LIB'])
279     if lenv['WITH_BF_ZLIB'] and not lenv['WITH_BF_STATICZLIB']:
280         syslibs += Split(lenv['BF_ZLIB_LIB'])
281     if lenv['WITH_BF_FFMPEG'] and not lenv['WITH_BF_STATICFFMPEG']:
282         syslibs += Split(lenv['BF_FFMPEG_LIB'])
283         if lenv['WITH_BF_OGG']:
284             syslibs += Split(lenv['BF_OGG_LIB'])
285     if lenv['WITH_BF_JACK'] and not lenv['WITH_BF_STATICJACK']:
286         syslibs += Split(lenv['BF_JACK_LIB'])
287     if lenv['WITH_BF_SNDFILE'] and not lenv['WITH_BF_STATICSNDFILE']:
288         syslibs += Split(lenv['BF_SNDFILE_LIB'])
289     if lenv['WITH_BF_FFTW3'] and not lenv['WITH_BF_STATICFFTW3']:
290         syslibs += Split(lenv['BF_FFTW3_LIB'])
291     if lenv['WITH_BF_ELTOPO']:
292         syslibs += Split(lenv['BF_LAPACK_LIB'])
293     if lenv['WITH_BF_SDL']:
294         syslibs += Split(lenv['BF_SDL_LIB'])
295     if not lenv['WITH_BF_STATICOPENGL']:
296         syslibs += Split(lenv['BF_OPENGL_LIB'])
297     if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw','linuxcross', 'win64-vc', 'win64-mingw'):
298         syslibs += Split(lenv['BF_PTHREADS_LIB'])
299     if lenv['WITH_BF_COLLADA'] and not lenv['WITH_BF_STATICOPENCOLLADA']:
300         syslibs.append(lenv['BF_PCRE_LIB'])
301         if lenv['BF_DEBUG'] and (lenv['OURPLATFORM'] != 'linux'):
302             syslibs += [colladalib+'_d' for colladalib in Split(lenv['BF_OPENCOLLADA_LIB'])]
303         else:
304             syslibs += Split(lenv['BF_OPENCOLLADA_LIB'])
305         syslibs.append(lenv['BF_EXPAT_LIB'])
306
307     if lenv['WITH_BF_JEMALLOC']:
308         if not lenv['WITH_BF_STATICJEMALLOC']:
309             syslibs += Split(lenv['BF_JEMALLOC_LIB'])
310
311     if lenv['OURPLATFORM']=='linux':
312         if lenv['WITH_BF_3DMOUSE']:
313             if not lenv['WITH_BF_STATIC3DMOUSE']:
314                 syslibs += Split(lenv['BF_3DMOUSE_LIB'])
315                 
316     if lenv['WITH_BF_BOOST'] and not lenv['WITH_BF_STATICBOOST']:
317         syslibs += Split(lenv['BF_BOOST_LIB'])
318
319     if not lenv['WITH_BF_STATICJPEG']:
320         syslibs += Split(lenv['BF_JPEG_LIB'])
321
322     if not lenv['WITH_BF_STATICPNG']:
323         syslibs += Split(lenv['BF_PNG_LIB'])
324
325     syslibs += lenv['LLIBS']
326
327     return syslibs
328
329 def propose_priorities():
330     print bc.OKBLUE+"Priorities:"+bc.ENDC
331     for t in possible_types:
332         print bc.OKGREEN+"\t"+t+bc.ENDC
333         new_priority = 0
334         curlib = libs[t]
335         sortlist = curlib.keys()
336         sortlist.sort()
337
338         for sk in sortlist:
339             v = curlib[sk]
340             #for p,v in sorted(libs[t].iteritems()):
341             print "\t\t",new_priority, v
342             new_priority += 5
343
344 # emits the necessary file objects for creator.c, to be used in creating
345 # the final blender executable
346 def creator(env):
347     sources = ['creator.c']# + Blender.buildinfo(env, "dynamic") + Blender.resources
348
349     incs = ['#/intern/guardedalloc', '#/source/blender/blenlib', '#/source/blender/blenkernel', '#/source/blender/editors/include', '#/source/blender/blenloader', '#/source/blender/imbuf', '#/source/blender/renderconverter', '#/source/blender/render/extern/include', '#/source/blender/windowmanager', '#/source/blender/makesdna', '#/source/blender/makesrna', '#/source/gameengine/BlenderRoutines', '#/extern/glew/include', '#/source/blender/gpu', '#/source/blender/freestyle', env['BF_OPENGL_INC']]
350
351     defs = []
352
353     if env['WITH_BF_BINRELOC']:
354         incs.append('#/extern/binreloc/include')
355         defs.append('WITH_BINRELOC')
356
357     if env['WITH_BF_SDL']:
358         defs.append('WITH_SDL')
359
360     if env['WITH_BF_LIBMV']:
361         incs.append('#/extern/libmv')
362         defs.append('WITH_LIBMV')
363
364     if env['WITH_BF_FFMPEG']:
365         defs.append('WITH_FFMPEG')
366
367     if env['WITH_BF_PYTHON']:
368         incs.append('#/source/blender/python')
369         defs.append('WITH_PYTHON')
370         if env['BF_DEBUG']:
371             defs.append('_DEBUG')
372
373     if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
374         incs.append(env['BF_PTHREADS_INC'])
375         incs.append('#/intern/utfconv')
376
377     env.Append(CPPDEFINES=defs)
378     env.Append(CPPPATH=incs)
379     obj = [env.Object(root_build_dir+'source/creator/creator/creator', ['#source/creator/creator.c'])]
380
381     return obj
382
383 ## TODO: see if this can be made in an emitter
384 def buildinfo(lenv, build_type):
385     """
386     Generate a buildinfo object
387     """
388     build_date = time.strftime ("%Y-%m-%d")
389     build_time = time.strftime ("%H:%M:%S")
390     build_rev = os.popen('svnversion').read()[:-1] # remove \n
391     if build_rev == '': 
392         build_rev = '-UNKNOWN-'
393     if lenv['BF_DEBUG']:
394         build_type = "Debug"
395         build_cflags = ' '.join(lenv['CFLAGS'] + lenv['CCFLAGS'] + lenv['BF_DEBUG_CCFLAGS'] + lenv['CPPFLAGS'])
396         build_cxxflags = ' '.join(lenv['CCFLAGS'] + lenv['CXXFLAGS'] + lenv['CPPFLAGS'])
397     else:
398         build_type = "Release"
399         build_cflags = ' '.join(lenv['CFLAGS'] + lenv['CCFLAGS'] + lenv['REL_CFLAGS'] + lenv['REL_CCFLAGS'] + lenv['CPPFLAGS'])
400         build_cxxflags = ' '.join(lenv['CCFLAGS'] + lenv['CXXFLAGS'] + lenv['REL_CXXFLAGS'] + lenv['REL_CCFLAGS'] + lenv['CPPFLAGS'])
401
402     build_linkflags = ' '.join(lenv['PLATFORM_LINKFLAGS'])
403
404     obj = []
405     if lenv['BF_BUILDINFO']:
406         lenv.Append (CPPDEFINES = ['BUILD_TIME=\\"%s\\"'%(build_time),
407                                     'BUILD_DATE=\\"%s\\"'%(build_date),
408                                     'BUILD_TYPE=\\"%s\\"'%(build_type),
409                                     'BUILD_REV=\\"%s\\"'%(build_rev),
410                                     'WITH_BUILDINFO',
411                                     'BUILD_PLATFORM=\\"%s:%s\\"'%(platform.system(), platform.architecture()[0]),
412                                     'BUILD_CFLAGS=\\"%s\\"'%(build_cflags),
413                                     'BUILD_CXXFLAGS=\\"%s\\"'%(build_cxxflags),
414                                     'BUILD_LINKFLAGS=\\"%s\\"'%(build_linkflags),
415                                     'BUILD_SYSTEM=\\"SCons\\"'
416                     ])
417
418         lenv.Append (CPPPATH = [root_build_dir+'source/blender/blenkernel'])
419
420         obj = [lenv.Object (root_build_dir+'source/creator/%s_buildinfo'%build_type, ['#source/creator/buildinfo.c'])]
421
422     return obj
423
424 ##### END LIB STUFF ############
425
426 ##### ACTION STUFF #############
427
428 def my_print_cmd_line(self, s, target, source, env):
429     sys.stdout.write(' ' * 70 + '\r')
430     sys.stdout.flush()
431     sys.stdout.write(s + "\r")
432     sys.stdout.flush()
433
434 def my_compile_print(target, source, env):
435     a = '%s' % (source[0])
436     d, f = os.path.split(a)
437     return bc.OKBLUE+"Compiling"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
438
439 def my_moc_print(target, source, env):
440     a = '%s' % (source[0])
441     d, f = os.path.split(a)
442     return bc.OKBLUE+"Creating MOC"+bc.ENDC+ " ==> '"+bc.OKGREEN+"%s" %(f) + "'"+bc.ENDC
443
444 def my_linking_print(target, source, env):
445     t = '%s' % (target[0])
446     d, f = os.path.split(t)
447     return bc.OKBLUE+"Linking library"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
448
449 def my_program_print(target, source, env):
450     t = '%s' % (target[0])
451     d, f = os.path.split(t)
452     return bc.OKBLUE+"Linking program"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
453
454 def msvc_hack(env):
455     static_lib = SCons.Tool.createStaticLibBuilder(env)
456     program = SCons.Tool.createProgBuilder(env)
457     
458     env['BUILDERS']['Library'] = static_lib
459     env['BUILDERS']['StaticLibrary'] = static_lib
460     env['BUILDERS']['Program'] = program
461         
462 def set_quiet_output(env):
463     mycaction = Action("$CCCOM", strfunction=my_compile_print)
464     myshcaction = Action("$SHCCCOM", strfunction=my_compile_print)
465     mycppaction = Action("$CXXCOM", strfunction=my_compile_print)
466     myshcppaction = Action("$SHCXXCOM", strfunction=my_compile_print)
467     mylibaction = Action("$ARCOM", strfunction=my_linking_print)
468     mylinkaction = Action("$LINKCOM", strfunction=my_program_print)
469
470     static_ob, shared_ob = SCons.Tool.createObjBuilders(env)
471     static_ob.add_action('.c', mycaction)
472     static_ob.add_action('.cpp', mycppaction)
473     static_ob.add_action('.cc', mycppaction)
474     shared_ob.add_action('.c', myshcaction)
475     shared_ob.add_action('.cc', myshcppaction)
476
477     static_lib = SCons.Builder.Builder(action = mylibaction,
478                                        emitter = '$LIBEMITTER',
479                                        prefix = '$LIBPREFIX',
480                                        suffix = '$LIBSUFFIX',
481                                        src_suffix = '$OBJSUFFIX',
482                                        src_builder = 'StaticObject')
483
484     program = SCons.Builder.Builder(action = mylinkaction,
485                                     emitter = '$PROGEMITTER',
486                                     prefix = '$PROGPREFIX',
487                                     suffix = '$PROGSUFFIX',
488                                     src_suffix = '$OBJSUFFIX',
489                                     src_builder = 'Object',
490                                     target_scanner = SCons.Defaults.ProgScan)
491
492     env['BUILDERS']['Object'] = static_ob
493     env['BUILDERS']['StaticObject'] = static_ob
494     env['BUILDERS']['StaticLibrary'] = static_lib
495     env['BUILDERS']['Library'] = static_lib
496     env['BUILDERS']['Program'] = program
497     if env['BF_LINE_OVERWRITE']:
498         SCons.Action._ActionAction.print_cmd_line = my_print_cmd_line
499
500 def untar_pybundle(from_tar,to_dir,exclude_re):
501     tar= tarfile.open(from_tar, mode='r')
502     exclude_re= list(exclude_re) #single re object or list of re objects
503     debug= 0 #list files instead of unpacking
504     good= []
505     if debug: print '\nFiles not being unpacked:\n'
506     for name in tar.getnames():
507         is_bad= 0
508         for r in exclude_re:
509             if r.match(name):
510                 is_bad=1
511                 if debug: print name
512                 break
513         if not is_bad:
514             good.append(tar.getmember(name))
515     if debug:
516         print '\nFiles being unpacked:\n'
517         for g in good:
518             print g
519     else:
520         tar.extractall(to_dir, good)
521
522 def my_winpybundle_print(target, source, env):
523     pass
524
525 def WinPyBundle(target=None, source=None, env=None):
526     import re
527     py_tar= env.subst( env['LCGDIR'] )
528     if py_tar[0]=='#':
529         py_tar= py_tar[1:]
530     if env['BF_DEBUG']:
531         py_tar+= '/release/python' + env['BF_PYTHON_VERSION'].replace('.','') + '_d.tar.gz'
532     else:
533         py_tar+= '/release/python' + env['BF_PYTHON_VERSION'].replace('.','') + '.tar.gz'
534
535     py_target = env.subst( env['BF_INSTALLDIR'] )
536     if py_target[0]=='#':
537         py_target=py_target[1:]
538     py_target = os.path.join(py_target, VERSION, 'python', 'lib')
539     def printexception(func,path,ex):
540         if os.path.exists(path): #do not report if path does not exist. eg on a fresh build.
541             print str(func) + ' failed on ' + str(path)
542     print "Trying to remove existing py bundle."
543     shutil.rmtree(py_target, False, printexception)
544     exclude_re=[re.compile('.*/test'),
545                 re.compile('^test'),
546                 re.compile('^distutils'),
547                 re.compile('^idlelib'),
548                 re.compile('^lib2to3'),
549                 re.compile('^tkinter'),
550                 re.compile('^_tkinter_d.pyd'),
551                 re.compile('^turtledemo'),
552                 re.compile('^turtle.py'),
553                 ]
554
555     print "Unpacking '" + py_tar + "' to '" + py_target + "'"
556     untar_pybundle(py_tar,py_target,exclude_re)
557
558 def  my_appit_print(target, source, env):
559     a = '%s' % (target[0])
560     d, f = os.path.split(a)
561     return "making bundle for " + f
562
563 def AppIt(target=None, source=None, env=None):
564     import shutil
565     import commands
566     import os.path
567     
568     
569     a = '%s' % (target[0])
570     builddir, b = os.path.split(a)
571     libdir = env['LCGDIR'][1:]
572     osxarch = env['MACOSX_ARCHITECTURE']
573     installdir = env['BF_INSTALLDIR']
574     print("compiled architecture: %s"%(osxarch))
575     print("Installing to %s"%(installdir))
576     # TODO, use tar.
577     python_zip = 'python_' + osxarch + '.zip' # set specific python_arch.zip
578     if env['WITH_OSX_STATICPYTHON']:
579         print("unzipping to app-bundle: %s"%(python_zip))
580     else:
581         print("dynamic build - make sure to have python3.x-framework installed")
582     bldroot = env.Dir('.').abspath
583     binary = env['BINARYKIND']
584      
585     sourcedir = bldroot + '/source/darwin/%s.app'%binary
586     sourceinfo = bldroot + "/source/darwin/%s.app/Contents/Info.plist"%binary
587     targetinfo = installdir +'/' + "%s.app/Contents/Info.plist"%binary
588     cmd = installdir + '/' +'%s.app'%binary
589     
590     if os.path.isdir(cmd):
591         shutil.rmtree(cmd)
592     shutil.copytree(sourcedir, cmd)
593     cmd = "cat %s | sed s/\$\{MACOSX_BUNDLE_SHORT_VERSION_STRING\}/%s/ | "%(sourceinfo,VERSION)
594     cmd += "sed s/\$\{MACOSX_BUNDLE_LONG_VERSION_STRING\}/%s,\ %s/g > %s"%(VERSION,time.strftime("%Y-%b-%d"),targetinfo)
595     commands.getoutput(cmd)
596     cmd = 'cp %s/%s %s/%s.app/Contents/MacOS/%s'%(builddir, binary,installdir, binary, binary)
597     commands.getoutput(cmd)
598     cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/'%(installdir, binary, VERSION)
599     commands.getoutput(cmd)
600     cmd = installdir + '/%s.app/Contents/MacOS/%s'%(binary,VERSION)
601
602     # blenderplayer doesn't need all the files
603     if binary == 'blender':
604         cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/datafiles'%(installdir, binary, VERSION)
605         commands.getoutput(cmd)
606         cmd = 'cp -R %s/release/datafiles/locale %s/%s.app/Contents/MacOS/%s/datafiles/'%(bldroot,installdir,binary,VERSION)
607         commands.getoutput(cmd)
608         cmd = 'cp -R %s/release/datafiles/fonts %s/%s.app/Contents/MacOS/%s/datafiles/'%(bldroot,installdir,binary,VERSION)
609         commands.getoutput(cmd)
610         if env['WITH_BF_OCIO']:
611             cmd = 'cp -R %s/release/datafiles/colormanagement %s/%s.app/Contents/MacOS/%s/datafiles/'%(bldroot,installdir,binary,VERSION)
612             commands.getoutput(cmd)
613         cmd = 'cp -R %s/release/scripts %s/%s.app/Contents/MacOS/%s/'%(bldroot,installdir,binary,VERSION)
614         commands.getoutput(cmd)
615
616         if VERSION_RELEASE_CYCLE == "release":
617             cmd = 'rm -rf %s/%s.app/Contents/MacOS/%s/scripts/addons_contrib'%(installdir,binary,VERSION)
618             commands.getoutput(cmd)
619
620         if env['WITH_BF_CYCLES']:
621             croot = '%s/intern/cycles' % (bldroot)
622             cinstalldir = '%s/%s.app/Contents/MacOS/%s/scripts/addons/cycles' % (installdir,binary,VERSION)
623
624             cmd = 'mkdir %s' % (cinstalldir)
625             commands.getoutput(cmd)
626             cmd = 'mkdir %s/kernel' % (cinstalldir)
627             commands.getoutput(cmd)
628             cmd = 'mkdir %s/lib' % (cinstalldir)
629             commands.getoutput(cmd)
630             cmd = 'cp -R %s/blender/addon/*.py %s/' % (croot, cinstalldir)
631             commands.getoutput(cmd)
632             cmd = 'cp -R %s/doc/license %s/license' % (croot, cinstalldir)
633             commands.getoutput(cmd)
634             cmd = 'cp -R %s/kernel/*.h %s/kernel/*.cl %s/kernel/*.cu %s/kernel/' % (croot, croot, croot, cinstalldir)
635             commands.getoutput(cmd)
636             cmd = 'cp -R %s/kernel/svm %s/util/util_color.h %s/util/util_math.h %s/util/util_transform.h %s/util/util_types.h %s/kernel/' % (croot, croot, croot, croot, croot, cinstalldir)
637             commands.getoutput(cmd)
638             cmd = 'cp -R %s/../intern/cycles/kernel/*.cubin %s/lib/' % (builddir, cinstalldir)
639             commands.getoutput(cmd)
640
641     if env['WITH_OSX_STATICPYTHON']:
642         cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/python/'%(installdir,binary, VERSION)
643         commands.getoutput(cmd)
644         cmd = 'unzip -q %s/release/%s -d %s/%s.app/Contents/MacOS/%s/python/'%(libdir,python_zip,installdir,binary,VERSION)
645         commands.getoutput(cmd)
646
647     cmd = 'chmod +x  %s/%s.app/Contents/MacOS/%s'%(installdir,binary, binary)
648     commands.getoutput(cmd)
649     cmd = 'find %s/%s.app -name .svn -prune -exec rm -rf {} \;'%(installdir, binary)
650     commands.getoutput(cmd)
651     cmd = 'find %s/%s.app -name .DS_Store -exec rm -rf {} \;'%(installdir, binary)
652     commands.getoutput(cmd)
653     cmd = 'find %s/%s.app -name __MACOSX -exec rm -rf {} \;'%(installdir, binary)
654     commands.getoutput(cmd)
655     if env['CC'][:-2].endswith('4.6'): # for correct errorhandling with gcc 4.6.x we need the gcc.dylib to link, thus distribute in app-bundle
656         cmd = 'mkdir %s/%s.app/Contents/MacOS/lib'%(installdir, binary)
657         commands.getoutput(cmd)
658         instname = env['BF_CXX']
659         cmd = 'cp %s/lib/libgcc_s.1.dylib %s/%s.app/Contents/MacOS/lib/'%(instname, installdir, binary)
660         commands.getoutput(cmd)
661         cmd = 'install_name_tool -id @executable_path/lib/libgcc_s.1.dylib %s/%s.app/Contents/MacOS/lib/libgcc_s.1.dylib'%(installdir, binary)
662         commands.getoutput(cmd)
663         cmd = 'install_name_tool -change %s/lib/libgcc_s.1.dylib  @executable_path/lib/libgcc_s.1.dylib %s/%s.app/Contents/MacOS/%s'%(instname, installdir, binary, binary)
664         commands.getoutput(cmd)
665         cmd = 'rm -rf  %s/set_simulation_threads.app'%(installdir) # first clear omp_num_threads applescript
666         commands.getoutput(cmd)
667         cmd = 'cp -R %s/source/darwin/set_simulation_threads.app %s/'%(bldroot, installdir) # copy the omp_num_threads applescript
668         commands.getoutput(cmd)
669
670 # extract copy system python, be sure to update other build systems
671 # when making changes to the files that are copied.
672 def my_unixpybundle_print(target, source, env):
673     pass
674
675 def UnixPyBundle(target=None, source=None, env=None):
676     # Any Unix except osx
677     #-- VERSION/python/lib/python3.1
678     
679     import commands
680     
681     def run(cmd):
682         print 'Install command:', cmd
683         commands.getoutput(cmd)
684
685     dir = os.path.join(env['BF_INSTALLDIR'], VERSION)
686
687     lib = env['BF_PYTHON_LIBPATH'].split(os.sep)[-1]
688     target_lib = "lib64" if lib == "lib64" else "lib"
689
690     py_src =    env.subst( env['BF_PYTHON_LIBPATH'] + '/python'+env['BF_PYTHON_VERSION'] )
691     py_target =    env.subst( dir + '/python/' + target_lib + '/python'+env['BF_PYTHON_VERSION'] )
692     
693     # This is a bit weak, but dont install if its been installed before, makes rebuilds quite slow.
694     if os.path.exists(py_target):
695         print 'Using existing python from:'
696         print '\t"%s"' %            py_target
697         print '\t(skipping copy)\n'
698         return
699
700     # Copied from source/creator/CMakeLists.txt, keep in sync.
701     print 'Install python from:'
702     print '\t"%s" into...' % py_src
703     print '\t"%s"\n' % py_target
704
705     run("rm -rf '%s'" % py_target)
706     try:
707         os.makedirs(os.path.dirname(py_target)) # the final part is copied
708     except:
709         pass
710
711     run("cp -R '%s' '%s'" % (py_src, os.path.dirname(py_target)))
712     run("rm -rf '%s/distutils'" % py_target)
713     run("rm -rf '%s/lib2to3'" % py_target)
714     run("rm -rf '%s/config'" % py_target)
715
716     for f in os.listdir(py_target):
717         if f.startswith("config-"):
718             run("rm -rf '%s/%s'" % (py_target, f))
719
720     run("rm -rf '%s/site-packages'" % py_target)
721     run("mkdir '%s/site-packages'" % py_target)    # python needs it.'
722     run("rm -rf '%s/idlelib'" % py_target)
723     run("rm -rf '%s/tkinter'" % py_target)
724     run("rm -rf '%s/turtledemo'" % py_target)
725     run("rm -r '%s/turtle.py'" % py_target)
726     run("rm -f '%s/lib-dynload/_tkinter.so'" % py_target)
727
728     if env['WITH_BF_PYTHON_INSTALL_NUMPY']:
729         numpy_src = py_src + "/site-packages/numpy"
730         numpy_target = py_target + "/site-packages/numpy"
731
732         if os.path.exists(numpy_src):
733             print 'Install numpy from:'
734             print '\t"%s" into...' % numpy_src
735             print '\t"%s"\n' % numpy_target
736
737             run("cp -R '%s' '%s'" % (numpy_src, os.path.dirname(numpy_target)))
738         else:
739             print 'Failed to find numpy at %s, skipping copying' % numpy_src
740
741     run("find '%s' -type d -name 'test' -prune -exec rm -rf {} ';'" % py_target)
742     run("find '%s' -type d -name '__pycache__' -exec rm -rf {} ';'" % py_target)
743     run("find '%s' -name '*.py[co]' -exec rm -rf {} ';'" % py_target)
744     run("find '%s' -name '*.so' -exec strip -s {} ';'" % py_target)
745
746 #### END ACTION STUFF #########
747
748 def bsc(env, target, source):
749     
750     bd = os.path.dirname(target[0].abspath)
751     bscfile = '\"'+target[0].abspath+'\"'
752     bscpathcollect = '\"'+bd + os.sep + '*.sbr\"'
753     bscpathtmp = '\"'+bd + os.sep + 'bscmake.tmp\"'
754
755     os.system('dir /b/s '+bscpathcollect+' >'+bscpathtmp)
756
757     myfile = open(bscpathtmp[1:-1], 'r')
758     lines = myfile.readlines()
759     myfile.close()
760
761     newfile = open(bscpathtmp[1:-1], 'w')
762     for l in lines:
763         newfile.write('\"'+l[:-1]+'\"\n')
764     newfile.close()
765                 
766     os.system('bscmake /nologo /n /o'+bscfile+' @'+bscpathtmp)
767     os.system('del '+bscpathtmp)
768
769 class BlenderEnvironment(SConsEnvironment):
770
771     PyBundleActionAdded = False
772
773     def BlenderRes(self=None, libname=None, source=None, libtype=['core'], priority=[100]):
774         global libs
775         if not self or not libname or not source:
776             print bc.FAIL+'Cannot continue.  Missing argument for BlenderRes '+libname+bc.ENDC
777             self.Exit()
778         if self['OURPLATFORM'] not in ('win32-vc','win32-mingw','linuxcross', 'win64-vc', 'win64-mingw'):
779             print bc.FAIL+'BlenderRes is for windows only!'+bc.END
780             self.Exit()
781         
782         print bc.HEADER+'Configuring resource '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC
783         lenv = self.Clone()
784         if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
785             res = lenv.RES('#'+root_build_dir+'lib/'+libname, source)
786         else:
787             res = lenv.RES(root_build_dir+'lib/'+libname, source)
788
789         
790         SConsEnvironment.Default(self, res)
791         resources.append(res)
792
793     def BlenderLib(self=None, libname=None, sources=None, includes=[], defines=[], libtype='common', priority = 100, compileflags=None, cc_compileflags=None, cxx_compileflags=None, cc_compilerchange=None, cxx_compilerchange=None):
794         global vcp
795         if not self or not libname or not sources:
796             print bc.FAIL+'Cannot continue. Missing argument for BuildBlenderLib '+libname+bc.ENDC
797             self.Exit()
798
799         def list_substring(quickie, libname):
800             for q in quickie:
801                 if libname.find(q) != -1:
802                     return True
803             return False
804
805         if list_substring(quickie, libname) or len(quickie)==0:
806             if list_substring(quickdebug, libname):
807                 print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname +bc.ENDC+bc.OKBLUE+ " (debug mode)" + bc.ENDC
808             else:
809                 print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname + bc.ENDC
810             lenv = self.Clone()
811             lenv.Append(CPPPATH=includes)
812             lenv.Append(CPPDEFINES=defines)
813             if lenv['BF_DEBUG'] or (libname in quickdebug):
814                 lenv.Append(CFLAGS = lenv['BF_DEBUG_CFLAGS'])
815                 lenv.Append(CCFLAGS = lenv['BF_DEBUG_CCFLAGS'])
816                 lenv.Append(CXXFLAGS = lenv['BF_DEBUG_CXXFLAGS'])
817             else:
818                 lenv.Append(CFLAGS = lenv['REL_CFLAGS'])
819                 lenv.Append(CCFLAGS = lenv['REL_CCFLAGS'])
820                 lenv.Append(CXXFLAGS = lenv['REL_CXXFLAGS'])
821             if lenv['BF_PROFILE']:
822                 lenv.Append(CFLAGS = lenv['BF_PROFILE_CFLAGS'])
823                 lenv.Append(CCFLAGS = lenv['BF_PROFILE_CCFLAGS'])
824                 lenv.Append(CXXFLAGS = lenv['BF_PROFILE_CXXFLAGS'])
825             if compileflags:
826                 lenv.Replace(CFLAGS = compileflags)
827             if cc_compileflags:
828                 lenv.Replace(CCFLAGS = cc_compileflags)
829             if cxx_compileflags:
830                 lenv.Replace(CXXFLAGS = cxx_compileflags)
831             if cc_compilerchange:
832                 lenv.Replace(CC = cc_compilerchange)
833             if cxx_compilerchange:
834                 lenv.Replace(CXX = cxx_compilerchange)
835             lenv.Append(CFLAGS = lenv['C_WARN'])
836             lenv.Append(CCFLAGS = lenv['CC_WARN'])
837             lenv.Append(CXXFLAGS = lenv['CXX_WARN'])
838
839             if lenv['OURPLATFORM'] == 'win64-vc':
840                 lenv.Append(LINKFLAGS = ['/MACHINE:X64'])
841
842             if lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
843                 if lenv['BF_DEBUG']:
844                     lenv.Append(CCFLAGS = ['/MTd'])
845                 else:
846                     lenv.Append(CCFLAGS = ['/MT'])
847             
848             targetdir = root_build_dir+'lib/' + libname
849             if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
850                 targetdir = '#'+targetdir
851             lib = lenv.Library(target= targetdir, source=sources)
852             SConsEnvironment.Default(self, lib) # we add to default target, because this way we get some kind of progress info during build
853             if self['BF_MSVS'] and self['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
854                 #if targetdir[0] == '#':
855                 #    targetdir = targetdir[1:-1]
856                 print "! ",targetdir+ '.vcproj' # + self['MSVSPROJECTSUFFIX']
857                 vcproject = self.MSVSProject(target = targetdir + '.vcproj', # + self['MSVSPROJECTSUFFIX'],
858                          srcs = sources,
859                          buildtarget = lib,
860                          variant = 'Release',
861                          auto_build_solution=0)
862                 vcp.append(vcproject)
863                 SConsEnvironment.Default(self, vcproject)
864         else:
865             print bc.WARNING+'Not building '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC+' for '+bc.OKBLUE+'BF_QUICK'+bc.ENDC
866         # note: libs is a global
867         add_lib_to_dict(self, libs, libtype, libname, priority)
868
869     def BlenderProg(self=None, builddir=None, progname=None, sources=None, libs=None, libpath=None, binarykind=''):
870         global vcp
871         print bc.HEADER+'Configuring program '+bc.ENDC+bc.OKGREEN+progname+bc.ENDC
872         lenv = self.Clone()
873         lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
874         if lenv['OURPLATFORM'] in ('win32-mingw', 'win64-mingw', 'linuxcross', 'cygwin', 'linux'):
875             lenv.Replace(LINK = '$CXX')
876         if lenv['OURPLATFORM'] in ('win32-vc', 'cygwin', 'win64-vc'):
877             if lenv['BF_DEBUG']:
878                 lenv.Prepend(LINKFLAGS = ['/DEBUG','/PDB:'+progname+'.pdb','/NODEFAULTLIB:libcmt'])
879         if  lenv['OURPLATFORM']=='linux':
880             if lenv['WITH_BF_PYTHON']:
881                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
882         if  lenv['OURPLATFORM']=='sunos5':
883             if lenv['WITH_BF_PYTHON']:
884                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
885             if lenv['CXX'].endswith('CC'):
886                 lenv.Replace(LINK = '$CXX')
887         if  lenv['OURPLATFORM']=='darwin':
888             if lenv['WITH_BF_PYTHON']:
889                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
890             lenv.Append(LINKFLAGS = lenv['BF_OPENGL_LINKFLAGS'])
891         if lenv['BF_PROFILE']:
892             lenv.Append(LINKFLAGS = lenv['BF_PROFILE_LINKFLAGS'])
893         if root_build_dir[0]==os.sep or root_build_dir[1]==':':
894             lenv.Append(LIBPATH=root_build_dir + '/lib')
895         lenv.Append(LIBPATH=libpath)
896         lenv.Append(LIBS=libs)
897         if lenv['WITH_BF_QUICKTIME']:
898             lenv.Append(LIBS = lenv['BF_QUICKTIME_LIB'])
899             lenv.Append(LIBPATH = lenv['BF_QUICKTIME_LIBPATH'])
900         prog = lenv.Program(target=builddir+'bin/'+progname, source=sources)
901         if lenv['BF_DEBUG'] and lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc') and lenv['BF_BSC']:
902             f = lenv.File(progname + '.bsc', builddir)
903             brs = lenv.Command(f, prog, [bsc])
904             SConsEnvironment.Default(self, brs)
905         SConsEnvironment.Default(self, prog)
906         if self['BF_MSVS'] and self['OURPLATFORM'] in ('win32-vc', 'win64-vc') and progname == 'blender':
907             print "! ",builddir + "/" + progname + '.sln'
908             sln = self.MSVSProject(target = builddir + "/" + progname + '.sln',
909                      projects= vcp,
910                      variant = 'Release')
911             SConsEnvironment.Default(self, sln)
912         program_list.append(prog)
913         if  lenv['OURPLATFORM']=='darwin':
914             lenv['BINARYKIND'] = binarykind
915             lenv.AddPostAction(prog,Action(AppIt,strfunction=my_appit_print))
916         elif os.sep == '/' and lenv['OURPLATFORM'] != 'linuxcross': # any unix (except cross-compilation)
917             if lenv['WITH_BF_PYTHON']:
918                 if (not lenv['WITHOUT_BF_INSTALL'] and 
919                     not lenv['WITHOUT_BF_PYTHON_INSTALL'] and 
920                     not lenv['WITHOUT_BF_PYTHON_UNPACK'] and 
921                     not BlenderEnvironment.PyBundleActionAdded):
922                     lenv.AddPostAction(prog,Action(UnixPyBundle,strfunction=my_unixpybundle_print))
923                     BlenderEnvironment.PyBundleActionAdded = True
924         elif lenv['OURPLATFORM'].startswith('win') or lenv['OURPLATFORM'] == 'linuxcross': # windows or cross-compilation
925             if lenv['WITH_BF_PYTHON']:
926                 if (not lenv['WITHOUT_BF_PYTHON_INSTALL'] and 
927                     not lenv['WITHOUT_BF_PYTHON_UNPACK'] and 
928                     not BlenderEnvironment.PyBundleActionAdded):
929                     lenv.AddPostAction(prog,Action(WinPyBundle,strfunction=my_winpybundle_print))
930                     BlenderEnvironment.PyBundleActionAdded = True
931         return prog
932
933     def Glob(lenv, pattern):
934         path = string.replace(GetBuildPath(lenv,'SConscript'),'SConscript', '')
935         files = []
936         for i in glob.glob(path + pattern):
937             files.append(string.replace(i, path, ''))
938         return files