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