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