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