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