scons support for extracting python from the system on unix os's
[blender.git] / 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
24 from SCons.Script.SConscript import SConsEnvironment
25 import SCons.Action
26 import SCons.Util
27 import SCons.Builder
28 import SCons.Tool
29 import bcolors
30 bc = bcolors.bcolors()
31
32 Split = SCons.Util.Split
33 Action = SCons.Action.Action
34 Builder = SCons.Builder.Builder
35 GetBuildPath = SConsEnvironment.GetBuildPath
36
37 # a few globals
38 root_build_dir = ''
39 doc_build_dir = ''
40 quickie = None # Anything else than None if BF_QUICK has been passed
41 quicklist = [] # The list of libraries/programs to compile during a quickie
42 program_list = [] # A list holding Nodes to final binaries, used to create installs
43 arguments = None
44 targets = None
45 resources = []
46
47 #some internals
48 blenderdeps = [] # don't manipulate this one outside this module!
49
50 ##### LIB STUFF ##########
51
52 possible_types = ['core'] # can be set in ie. SConstruct
53 libs = {}
54 vcp = []
55
56 def getresources():
57         return resources
58
59 def init_lib_dict():
60         for pt in possible_types:
61                 libs[pt] = {}
62
63 # helper func for add_lib_to_dict
64 def internal_lib_to_dict(dict = None, libtype = None, libname = None, priority = 100):
65         if not libname in dict[libtype]:
66                 done = None
67                 while not done:
68                         if dict[libtype].has_key(priority):
69                                 priority = priority + 1
70                         else:
71                                 done = True
72                 dict[libtype][priority] = libname
73
74 # libtype and priority can both be lists, for defining lib in multiple places
75 def add_lib_to_dict(env, dict = None, libtype = None, libname = None, priority = 100):
76         if not dict or not libtype or not libname:
77                 print "Passed wrong arg"
78                 env.Exit()
79
80         if type(libtype) is str and type(priority) is int:
81                 internal_lib_to_dict(dict, libtype, libname, priority)
82         elif type(libtype) is list and type(priority) is list:
83                 if len(libtype)==len(priority):
84                         for lt, p in zip(libtype, priority):
85                                 internal_lib_to_dict(dict, lt, libname, p)
86                 else:
87                         print "libtype and priority lists are unequal in length"
88                         env.Exit()
89         else:
90                 print "Wrong type combinations for libtype and priority. Only str and int or list and list"
91                 env.Exit()
92
93 def create_blender_liblist(lenv = None, libtype = None):
94         if not lenv or not libtype:
95                 print "missing arg"
96
97         lst = []
98         if libtype in possible_types:
99                 curlib = libs[libtype]
100                 sortlist = curlib.keys()
101                 sortlist.sort()
102                 for sk in sortlist:
103                         v = curlib[sk]
104                         target = os.path.abspath(os.getcwd() + os.sep + root_build_dir + 'lib' + os.sep +lenv['LIBPREFIX'] + v + lenv['LIBSUFFIX'])
105                         lst.append(target)
106
107         return lst
108
109 ## TODO: static linking
110 def setup_staticlibs(lenv):
111         statlibs = [
112                 #here libs for static linking
113         ]
114         libincs = [
115                 '/usr/lib',
116                 lenv['BF_OPENGL_LIBPATH'],
117                 lenv['BF_JPEG_LIBPATH'],
118                 lenv['BF_PNG_LIBPATH'],
119                 lenv['BF_ZLIB_LIBPATH'],
120                 lenv['BF_LIBSAMPLERATE_LIBPATH'],
121                 lenv['BF_ICONV_LIBPATH']
122                 ]
123
124         libincs += Split(lenv['BF_FREETYPE_LIBPATH'])
125         if lenv['WITH_BF_PYTHON']:
126                 libincs += Split(lenv['BF_PYTHON_LIBPATH'])
127         if lenv['WITH_BF_SDL']:
128                 libincs += Split(lenv['BF_SDL_LIBPATH'])
129         if lenv['WITH_BF_FFMPEG']:
130                 libincs += Split(lenv['BF_FFMPEG_LIBPATH'])
131         if lenv['WITH_BF_JACK']:
132                 libincs += Split(lenv['BF_JACK_LIBPATH'])
133         if lenv['WITH_BF_OPENEXR']:
134                 libincs += Split(lenv['BF_OPENEXR_LIBPATH'])
135                 if lenv['WITH_BF_STATICOPENEXR']:
136                         statlibs += Split(lenv['BF_OPENEXR_LIB_STATIC'])
137         if lenv['WITH_BF_FFTW3']:
138                 libincs += Split(lenv['BF_FFTW3_LIBPATH'])
139         if lenv['WITH_BF_INTERNATIONAL']:
140                 libincs += Split(lenv['BF_GETTEXT_LIBPATH'])
141         if lenv['WITH_BF_OPENAL']:
142                 libincs += Split(lenv['BF_OPENAL_LIBPATH'])
143                 if lenv['WITH_BF_STATICOPENAL']:
144                         statlibs += Split(lenv['BF_OPENAL_LIB_STATIC'])
145         if lenv['WITH_BF_STATICOPENGL']:
146                 statlibs += Split(lenv['BF_OPENGL_LIB_STATIC'])
147         if lenv['WITH_BF_STATICCXX']:
148                 statlibs += Split(lenv['BF_CXX_LIB_STATIC'])
149
150         if lenv['WITH_BF_PYTHON'] and lenv['WITH_BF_STATICPYTHON']:
151                 statlibs += Split(lenv['BF_PYTHON_LIB_STATIC'])
152
153         if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
154                 libincs += Split(lenv['BF_PTHREADS_LIBPATH'])
155
156         return statlibs, libincs
157
158 def setup_syslibs(lenv):
159         syslibs = [
160                 
161                 lenv['BF_JPEG_LIB'],
162                 lenv['BF_PNG_LIB'],
163                 lenv['BF_ZLIB_LIB'],
164                 lenv['BF_LIBSAMPLERATE_LIB']
165                 ]
166
167         syslibs += Split(lenv['BF_FREETYPE_LIB'])
168         if lenv['WITH_BF_PYTHON'] and not lenv['WITH_BF_STATICPYTHON']:
169                 if lenv['BF_DEBUG'] and lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
170                         syslibs.append(lenv['BF_PYTHON_LIB']+'_d')
171                 else:
172                         syslibs.append(lenv['BF_PYTHON_LIB'])
173         if lenv['WITH_BF_INTERNATIONAL']:
174                 syslibs += Split(lenv['BF_GETTEXT_LIB'])
175         if lenv['WITH_BF_OPENAL']:
176                 if not lenv['WITH_BF_STATICOPENAL']:
177                         syslibs += Split(lenv['BF_OPENAL_LIB'])
178         if lenv['WITH_BF_OPENMP'] and lenv['CC'] != 'icc':
179                 if lenv['CC'] == 'cl.exe':
180                         syslibs += ['vcomp']
181                 else:
182                         syslibs += ['gomp']
183         if lenv['WITH_BF_ICONV']:
184                 syslibs += Split(lenv['BF_ICONV_LIB'])
185         if lenv['WITH_BF_OPENEXR']:
186                 if not lenv['WITH_BF_STATICOPENEXR']:
187                         syslibs += Split(lenv['BF_OPENEXR_LIB'])
188         if lenv['WITH_BF_FFMPEG']:
189                 syslibs += Split(lenv['BF_FFMPEG_LIB'])
190                 if lenv['WITH_BF_OGG']:
191                         syslibs += Split(lenv['BF_OGG_LIB'])
192         if lenv['WITH_BF_JACK']:
193                         syslibs += Split(lenv['BF_JACK_LIB'])
194         if lenv['WITH_BF_FFTW3']:
195                 syslibs += Split(lenv['BF_FFTW3_LIB'])
196         if lenv['WITH_BF_SDL']:
197                 syslibs += Split(lenv['BF_SDL_LIB'])
198         if not lenv['WITH_BF_STATICOPENGL']:
199                 syslibs += Split(lenv['BF_OPENGL_LIB'])
200         if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw','linuxcross', 'win64-vc'):
201                 syslibs += Split(lenv['BF_PTHREADS_LIB'])
202         if lenv['WITH_BF_LCMS']:
203                 syslibs.append(lenv['BF_LCMS_LIB'])
204
205
206         syslibs += lenv['LLIBS']
207
208         return syslibs
209
210 def propose_priorities():
211         print bc.OKBLUE+"Priorities:"+bc.ENDC
212         for t in possible_types:
213                 print bc.OKGREEN+"\t"+t+bc.ENDC
214                 new_priority = 0
215                 curlib = libs[t]
216                 sortlist = curlib.keys()
217                 sortlist.sort()
218
219                 for sk in sortlist:
220                         v = curlib[sk]
221                         #for p,v in sorted(libs[t].iteritems()):
222                         print "\t\t",new_priority, v
223                         new_priority += 5
224
225 ## TODO: see if this can be made in an emitter
226 def buildinfo(lenv, build_type):
227         """
228         Generate a buildinfo object
229         """
230         build_date = time.strftime ("%Y-%m-%d")
231         build_time = time.strftime ("%H:%M:%S")
232         build_rev = os.popen('svnversion').read()[:-1] # remove \n
233
234         obj = []
235         if lenv['BF_BUILDINFO']:
236                 if sys.platform=='win32':
237                         build_info_file = open("source/creator/winbuildinfo.h", 'w')
238                         build_info_file.write("char *build_date=\"%s\";\n"%build_date)
239                         build_info_file.write("char *build_time=\"%s\";\n"%build_time)
240                         build_info_file.write("char *build_rev=\"%s\";\n"%build_rev)
241                         build_info_file.write("char *build_platform=\"win32\";\n")
242                         build_info_file.write("char *build_type=\"dynamic\";\n")
243                         build_info_file.close()
244                         lenv.Append (CPPDEFINES = ['NAN_BUILDINFO', 'BUILD_DATE'])
245                 else:
246                         lenv.Append (CPPDEFINES = ['BUILD_TIME=\'"%s"\''%(build_time),
247                                                                                 'BUILD_DATE=\'"%s"\''%(build_date),
248                                                                                 'BUILD_TYPE=\'"dynamic"\'',
249                                                                                 'BUILD_REV=\'"%s"\''%(build_rev),
250                                                                                 'NAN_BUILDINFO',
251                                                                                 'BUILD_PLATFORM=\'"%s"\''%(sys.platform)])
252                 obj = [lenv.Object (root_build_dir+'source/creator/%s_buildinfo'%build_type,
253                                                 [root_build_dir+'source/creator/buildinfo.c'])]
254         return obj
255
256 ##### END LIB STUFF ############
257
258 ##### ACTION STUFF #############
259
260 def my_compile_print(target, source, env):
261         a = '%s' % (source[0])
262         d, f = os.path.split(a)
263         return bc.OKBLUE+"Compiling"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
264
265 def my_moc_print(target, source, env):
266         a = '%s' % (source[0])
267         d, f = os.path.split(a)
268         return bc.OKBLUE+"Creating MOC"+bc.ENDC+ " ==> '"+bc.OKGREEN+"%s" %(f) + "'"+bc.ENDC
269
270 def my_linking_print(target, source, env):
271         t = '%s' % (target[0])
272         d, f = os.path.split(t)
273         return bc.OKBLUE+"Linking library"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
274
275 def my_program_print(target, source, env):
276         t = '%s' % (target[0])
277         d, f = os.path.split(t)
278         return bc.OKBLUE+"Linking program"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
279
280 def msvc_hack(env):
281         static_lib = SCons.Tool.createStaticLibBuilder(env)
282         program = SCons.Tool.createProgBuilder(env)
283         
284         env['BUILDERS']['Library'] = static_lib
285         env['BUILDERS']['StaticLibrary'] = static_lib
286         env['BUILDERS']['Program'] = program
287                 
288 def set_quiet_output(env):
289         mycaction = Action("$CCCOM", strfunction=my_compile_print)
290         myshcaction = Action("$SHCCCOM", strfunction=my_compile_print)
291         mycppaction = Action("$CXXCOM", strfunction=my_compile_print)
292         myshcppaction = Action("$SHCXXCOM", strfunction=my_compile_print)
293         mylibaction = Action("$ARCOM", strfunction=my_linking_print)
294         mylinkaction = Action("$LINKCOM", strfunction=my_program_print)
295
296         static_ob, shared_ob = SCons.Tool.createObjBuilders(env)
297         static_ob.add_action('.c', mycaction)
298         static_ob.add_action('.cpp', mycppaction)
299         shared_ob.add_action('.c', myshcaction)
300         shared_ob.add_action('.cpp', myshcppaction)
301
302         static_lib = SCons.Builder.Builder(action = mylibaction,
303                                                                            emitter = '$LIBEMITTER',
304                                                                            prefix = '$LIBPREFIX',
305                                                                            suffix = '$LIBSUFFIX',
306                                                                            src_suffix = '$OBJSUFFIX',
307                                                                            src_builder = 'StaticObject')
308
309         program = SCons.Builder.Builder(action = mylinkaction,
310                                                                         emitter = '$PROGEMITTER',
311                                                                         prefix = '$PROGPREFIX',
312                                                                         suffix = '$PROGSUFFIX',
313                                                                         src_suffix = '$OBJSUFFIX',
314                                                                         src_builder = 'Object',
315                                                                         target_scanner = SCons.Defaults.ProgScan)
316
317         env['BUILDERS']['Object'] = static_ob
318         env['BUILDERS']['StaticObject'] = static_ob
319         env['BUILDERS']['StaticLibrary'] = static_lib
320         env['BUILDERS']['Library'] = static_lib
321         env['BUILDERS']['Program'] = program
322
323 def  my_appit_print(target, source, env):
324         a = '%s' % (target[0])
325         d, f = os.path.split(a)
326         return "making bundle for " + f
327
328 def AppIt(target=None, source=None, env=None):
329         import shutil
330         import commands
331         import os.path
332         
333         
334         a = '%s' % (target[0])
335         builddir, b = os.path.split(a)
336         libdir = env['LCGDIR'][1:]
337
338         bldroot = env.Dir('.').abspath
339         binary = env['BINARYKIND']
340          
341         if b=='verse':
342                 print bc.OKBLUE+"no bundle for verse"+bc.ENDC 
343                 return 0
344         
345         sourcedir = bldroot + '/source/darwin/%s.app'%binary
346         sourceinfo = bldroot + "/source/darwin/%s.app/Contents/Info.plist"%binary
347         targetinfo = builddir +'/' + "%s.app/Contents/Info.plist"%binary
348         cmd = builddir + '/' +'%s.app'%binary
349         
350         if os.path.isdir(cmd):
351                 shutil.rmtree(cmd)
352         shutil.copytree(sourcedir, cmd)
353         cmd = "cat %s | sed s/VERSION/`cat release/VERSION`/ | sed s/DATE/`date +'%%Y-%%b-%%d'`/ > %s"%(sourceinfo,targetinfo)
354         commands.getoutput(cmd)
355         cmd = 'cp %s/%s %s/%s.app/Contents/MacOS/%s'%(builddir, binary,builddir, binary, binary)
356         commands.getoutput(cmd)
357         cmd = 'mkdir %s/%s.app/Contents/MacOS/.blender/'%(builddir, binary)
358         print cmd
359         commands.getoutput(cmd)
360         cmd = builddir + '/%s.app/Contents/MacOS/.blender'%binary
361         shutil.copy(bldroot + '/bin/.blender/.bfont.ttf', cmd)
362         shutil.copy(bldroot + '/bin/.blender/.Blanguages', cmd)
363         cmd = 'cp -R %s/bin/.blender/locale %s/%s.app/Contents/Resources/'%(bldroot,builddir,binary)
364         commands.getoutput(cmd) 
365         cmd = 'cp -R %s/bin/.blender/locale %s/%s.app/Contents/MacOS/.blender/'%(bldroot,builddir,binary)
366         commands.getoutput(cmd) 
367         cmd = 'cp %s/bin/.blender/.Blanguages %s/%s.app/Contents/Resources/'%(bldroot,builddir,binary)
368         commands.getoutput(cmd) 
369         cmd = 'mkdir %s/%s.app/Contents/MacOS/.blender/python/'%(builddir,binary)
370         commands.getoutput(cmd) 
371         cmd = 'unzip -q %s/release/python.zip -d %s/%s.app/Contents/MacOS/.blender/python/'%(libdir,builddir,binary)
372         commands.getoutput(cmd) 
373         cmd = 'cp -R %s/release/scripts %s/%s.app/Contents/MacOS/.blender/'%(bldroot,builddir,binary)
374         commands.getoutput(cmd)
375         cmd = 'cp -R %s/release/ui %s/%s.app/Contents/MacOS/.blender/'%(bldroot,builddir,binary)
376         commands.getoutput(cmd)
377         cmd = 'cp -R %s/release/io %s/%s.app/Contents/MacOS/.blender/'%(bldroot,builddir,binary)
378         commands.getoutput(cmd)
379         cmd = 'chmod +x  %s/%s.app/Contents/MacOS/%s'%(builddir,binary, binary)
380         commands.getoutput(cmd)
381         cmd = 'find %s/%s.app -name .svn -prune -exec rm -rf {} \;'%(builddir, binary)
382         commands.getoutput(cmd)
383         cmd = 'find %s/%s.app -name .DS_Store -exec rm -rf {} \;'%(builddir, binary)
384         commands.getoutput(cmd)
385
386 # extract copy system python, be sure to update other build systems
387 # when making changes to the files that are copied.
388 def my_pyinst_print(target, source, env):
389         pass
390
391 def PyInstall(target=None, source=None, env=None):
392         # Any Unix except osx
393         #-- .blender/python/lib/python3.1
394         
395         import commands
396         
397         def run(cmd):
398                 print 'Install command:', cmd
399                 commands.getoutput(cmd)
400         
401         py_src =        env.subst( env['BF_PYTHON_LIBPATH'] + '/python'+env['BF_PYTHON_VERSION'] )
402         py_target =     env.subst( env['BF_INSTALLDIR'] + '/.blender/python/lib/python'+env['BF_PYTHON_VERSION'] )
403         
404         # Copied from source/creator/CMakeLists.txt, keep in sync.
405         print 'Install python from:'
406         print '\t"%s" into...' %        py_src
407         print '\t"%s"\n' %                      py_target
408         
409         run('rm -rf "%s"' % py_target)
410         try:    os.makedirs(os.path.dirname(py_target)) # the final part is copied
411         except:pass
412         
413         run('cp -R "%s" "%s"' % (py_src, os.path.dirname(py_target)))
414         run('rm -rf "%s/distutils"' % py_target)
415         run('rm -rf "%s/lib2to3"' % py_target)
416         run('rm -rf "%s/idlelib"' % py_target)
417         run('rm -rf "%s/tkinter"' % py_target)
418         run('rm -rf "%s/config"' % py_target)
419
420         run('rm -rf "%s/site-packages"' % py_target)
421         run('mkdir "%s/site-packages"' % py_target)    # python needs it.'
422
423         run('rm "%s/lib-dynload/_tkinter.so"' % py_target)
424         run('find "%s" -name "test" -prune -exec rm -rf {} \;' % py_target)
425         run('find "%s" -name "*.py?" -exec rm -rf {} \;' % py_target)
426         run('find "%s" -name "*.so"-exec strip -s {} \;' % py_target)
427
428 #### END ACTION STUFF #########
429
430 def bsc(env, target, source):
431         
432         bd = os.path.dirname(target[0].abspath)
433         bscfile = '\"'+target[0].abspath+'\"'
434         bscpathcollect = '\"'+bd + os.sep + '*.sbr\"'
435         bscpathtmp = '\"'+bd + os.sep + 'bscmake.tmp\"'
436
437         os.system('dir /b/s '+bscpathcollect+' >'+bscpathtmp)
438
439         myfile = open(bscpathtmp[1:-1], 'r')
440         lines = myfile.readlines()
441         myfile.close()
442
443         newfile = open(bscpathtmp[1:-1], 'w')
444         for l in lines:
445                 newfile.write('\"'+l[:-1]+'\"\n')
446         newfile.close()
447                                 
448         os.system('bscmake /nologo /n /o'+bscfile+' @'+bscpathtmp)
449         os.system('del '+bscpathtmp)
450
451 class BlenderEnvironment(SConsEnvironment):
452
453         def BlenderRes(self=None, libname=None, source=None, libtype=['core'], priority=[100]):
454                 global libs
455                 if not self or not libname or not source:
456                         print bc.FAIL+'Cannot continue.  Missing argument for BlenderRes '+libname+bc.ENDC
457                         self.Exit()
458                 if self['OURPLATFORM'] not in ('win32-vc','win32-mingw','linuxcross', 'win64-vc'):
459                         print bc.FAIL+'BlenderRes is for windows only!'+bc.END
460                         self.Exit()
461                 
462                 print bc.HEADER+'Configuring resource '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC
463                 lenv = self.Clone()
464                 res = lenv.RES('#'+root_build_dir+'lib/'+libname, source)
465                 
466                 SConsEnvironment.Default(self, res)
467                 resources.append(res)
468
469         def BlenderLib(self=None, libname=None, sources=None, includes=[], defines=[], libtype='common', priority = 100, compileflags=None, cc_compileflags=None, cxx_compileflags=None):
470                 global vcp
471                 if not self or not libname or not sources:
472                         print bc.FAIL+'Cannot continue. Missing argument for BuildBlenderLib '+libname+bc.ENDC
473                         self.Exit()
474
475                 def list_substring(quickie, libname):
476                         for q in quickie:
477                                 if libname.find(q) != -1:
478                                         return True
479                         return False
480
481                 if list_substring(quickie, libname) or len(quickie)==0:
482                         if list_substring(quickdebug, libname):
483                                 print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname +bc.ENDC+bc.OKBLUE+ " (debug mode)" + bc.ENDC
484                         else:
485                                 print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname + bc.ENDC
486                         lenv = self.Clone()
487                         lenv.Append(CPPPATH=includes)
488                         lenv.Append(CPPDEFINES=defines)
489                         if lenv['BF_DEBUG'] or (libname in quickdebug):
490                                         lenv.Append(CFLAGS = lenv['BF_DEBUG_CFLAGS'])
491                                         lenv.Append(CCFLAGS = lenv['BF_DEBUG_CCFLAGS'])
492                                         lenv.Append(CXXFLAGS = lenv['BF_DEBUG_CXXFLAGS'])
493                         else:
494                                         lenv.Append(CFLAGS = lenv['REL_CFLAGS'])
495                                         lenv.Append(CCFLAGS = lenv['REL_CCFLAGS'])
496                                         lenv.Append(CXXFLAGS = lenv['REL_CXXFLAGS'])
497                         if lenv['BF_PROFILE']:
498                                         lenv.Append(CFLAGS = lenv['BF_PROFILE_CFLAGS'])
499                                         lenv.Append(CCFLAGS = lenv['BF_PROFILE_CCFLAGS'])
500                                         lenv.Append(CXXFLAGS = lenv['BF_PROFILE_CXXFLAGS'])
501                         if compileflags:
502                                 lenv.Replace(CFLAGS = compileflags)
503                         if cc_compileflags:
504                                 lenv.Replace(CCFLAGS = cc_compileflags)
505                         if cxx_compileflags:
506                                 lenv.Replace(CXXFLAGS = cxx_compileflags)
507                         lenv.Append(CFLAGS = lenv['C_WARN'])
508                         lenv.Append(CCFLAGS = lenv['CC_WARN'])
509                         lenv.Append(CXXFLAGS = lenv['CXX_WARN'])
510
511                         if lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
512                                 if lenv['BF_DEBUG']:
513                                         lenv.Append(CCFLAGS = ['/MTd'])
514                                 else:
515                                         lenv.Append(CCFLAGS = ['/MT'])
516                         
517                         targetdir = root_build_dir+'lib/' + libname
518                         if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
519                                 targetdir = '#'+targetdir
520                         lib = lenv.Library(target= targetdir, source=sources)
521                         SConsEnvironment.Default(self, lib) # we add to default target, because this way we get some kind of progress info during build
522                         if self['BF_MSVS'] and self['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
523                                 #if targetdir[0] == '#':
524                                 #       targetdir = targetdir[1:-1]
525                                 print "! ",targetdir+ '.vcproj' # + self['MSVSPROJECTSUFFIX']
526                                 vcproject = self.MSVSProject(target = targetdir + '.vcproj', # + self['MSVSPROJECTSUFFIX'],
527                                                  srcs = sources,
528                                                  buildtarget = lib,
529                                                  variant = 'Release',
530                                                  auto_build_solution=0)
531                                 vcp.append(vcproject)
532                                 SConsEnvironment.Default(self, vcproject)
533                 else:
534                         print bc.WARNING+'Not building '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC+' for '+bc.OKBLUE+'BF_QUICK'+bc.ENDC
535                 # note: libs is a global
536                 add_lib_to_dict(self, libs, libtype, libname, priority)
537
538         def BlenderProg(self=None, builddir=None, progname=None, sources=None, includes=None, libs=None, libpath=None, binarykind=''):
539                 global vcp
540                 print bc.HEADER+'Configuring program '+bc.ENDC+bc.OKGREEN+progname+bc.ENDC
541                 lenv = self.Clone()
542                 if lenv['OURPLATFORM'] in ('win32-vc', 'cygwin', 'win64-vc'):
543                         lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
544                         lenv.Append(LINKFLAGS = ['/FORCE:MULTIPLE'])
545                         if lenv['BF_DEBUG']:
546                                 lenv.Prepend(LINKFLAGS = ['/DEBUG','/PDB:'+progname+'.pdb'])
547                 if  lenv['OURPLATFORM']=='linux2':
548                         lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
549                         if lenv['WITH_BF_PYTHON']:
550                                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
551                 if  lenv['OURPLATFORM']=='sunos5':
552                         lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
553                         if lenv['WITH_BF_PYTHON']:
554                                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
555                         if lenv['CXX'].endswith('CC'):
556                                  lenv.Replace(LINK = '$CXX')
557                 if  lenv['OURPLATFORM']=='darwin':
558                         lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
559                         if lenv['WITH_BF_PYTHON']:
560                                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
561                         lenv.Append(LINKFLAGS = lenv['BF_OPENGL_LINKFLAGS'])
562                 if lenv['BF_PROFILE']:
563                         lenv.Append(LINKFLAGS = lenv['BF_PROFILE_LINKFLAGS'])
564                 lenv.Append(CPPPATH=includes)
565                 if root_build_dir[0]==os.sep or root_build_dir[1]==':':
566                         lenv.Append(LIBPATH=root_build_dir + '/lib')
567                 lenv.Append(LIBPATH=libpath)
568                 lenv.Append(LIBS=libs)
569                 if lenv['WITH_BF_QUICKTIME']:
570                          lenv.Append(LIBS = lenv['BF_QUICKTIME_LIB'])
571                          lenv.Append(LIBPATH = lenv['BF_QUICKTIME_LIBPATH'])
572                 prog = lenv.Program(target=builddir+'bin/'+progname, source=sources)
573                 if lenv['BF_DEBUG'] and lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc') and lenv['BF_BSC']:
574                         f = lenv.File(progname + '.bsc', builddir)
575                         brs = lenv.Command(f, prog, [bsc])
576                         SConsEnvironment.Default(self, brs)
577                 SConsEnvironment.Default(self, prog)
578                 if self['BF_MSVS'] and self['OURPLATFORM'] in ('win32-vc', 'win64-vc') and progname == 'blender':
579                         print "! ",builddir + "/" + progname + '.sln'
580                         sln = self.MSVSProject(target = builddir + "/" + progname + '.sln',
581                                          projects= vcp,
582                                          variant = 'Release')
583                         SConsEnvironment.Default(self, sln)
584                 program_list.append(prog)
585                 if  lenv['OURPLATFORM']=='darwin':
586                         lenv['BINARYKIND'] = binarykind
587                         lenv.AddPostAction(prog,Action(AppIt,strfunction=my_appit_print))
588                 elif os.sep == '/': # any unix
589                         if lenv['WITH_BF_PYTHON']:
590                                 if not lenv['WITHOUT_BF_INSTALL']:
591                                         lenv.AddPostAction(prog,Action(PyInstall,strfunction=my_pyinst_print))
592                 
593                 return prog
594
595         def Glob(lenv, pattern):
596                 path = string.replace(GetBuildPath(lenv,'SConscript'),'SConscript', '')
597                 files = []
598                 for i in glob.glob(path + pattern):
599                         files.append(string.replace(i, path, ''))
600                 return files