One last try - this should fix the remaining issues:
[blender-staging.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                         if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
105                                 target = os.path.abspath(os.getcwd() + os.sep + root_build_dir + 'lib' + os.sep +lenv['LIBPREFIX'] + v + lenv['LIBSUFFIX'])
106                         else:
107                                 target = os.path.abspath(root_build_dir + 'lib' + os.sep +lenv['LIBPREFIX'] + v + lenv['LIBSUFFIX'])
108                         lst.append(target)
109
110         return lst
111
112 ## TODO: static linking
113 def setup_staticlibs(lenv):
114         statlibs = [
115                 #here libs for static linking
116         ]
117         libincs = [
118                 '/usr/lib',
119                 lenv['BF_OPENGL_LIBPATH'],
120                 lenv['BF_JPEG_LIBPATH'],
121                 lenv['BF_PNG_LIBPATH'],
122                 lenv['BF_ZLIB_LIBPATH'],
123                 lenv['BF_LIBSAMPLERATE_LIBPATH'],
124                 lenv['BF_ICONV_LIBPATH']
125                 ]
126
127         libincs += Split(lenv['BF_FREETYPE_LIBPATH'])
128         if lenv['WITH_BF_PYTHON']:
129                 libincs += Split(lenv['BF_PYTHON_LIBPATH'])
130         if lenv['WITH_BF_SDL']:
131                 libincs += Split(lenv['BF_SDL_LIBPATH'])
132         if lenv['WITH_BF_FFMPEG']:
133                 libincs += Split(lenv['BF_FFMPEG_LIBPATH'])
134         if lenv['WITH_BF_JACK']:
135                 libincs += Split(lenv['BF_JACK_LIBPATH'])
136         if lenv['WITH_BF_SNDFILE']:
137                 libincs += Split(lenv['BF_SNDFILE_LIBPATH'])
138         if lenv['WITH_BF_OPENEXR']:
139                 libincs += Split(lenv['BF_OPENEXR_LIBPATH'])
140                 if lenv['WITH_BF_STATICOPENEXR']:
141                         statlibs += Split(lenv['BF_OPENEXR_LIB_STATIC'])
142         if lenv['WITH_BF_FFTW3']:
143                 libincs += Split(lenv['BF_FFTW3_LIBPATH'])
144         if lenv['WITH_BF_INTERNATIONAL']:
145                 libincs += Split(lenv['BF_GETTEXT_LIBPATH'])
146         if lenv['WITH_BF_OPENAL']:
147                 libincs += Split(lenv['BF_OPENAL_LIBPATH'])
148                 if lenv['WITH_BF_STATICOPENAL']:
149                         statlibs += Split(lenv['BF_OPENAL_LIB_STATIC'])
150         if lenv['WITH_BF_STATICOPENGL']:
151                 statlibs += Split(lenv['BF_OPENGL_LIB_STATIC'])
152         if lenv['WITH_BF_STATICCXX']:
153                 statlibs += Split(lenv['BF_CXX_LIB_STATIC'])
154
155         if lenv['WITH_BF_PYTHON'] and lenv['WITH_BF_STATICPYTHON']:
156                 statlibs += Split(lenv['BF_PYTHON_LIB_STATIC'])
157
158         if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
159                 libincs += Split(lenv['BF_PTHREADS_LIBPATH'])
160
161         return statlibs, libincs
162
163 def setup_syslibs(lenv):
164         syslibs = [
165                 
166                 lenv['BF_JPEG_LIB'],
167                 lenv['BF_PNG_LIB'],
168                 lenv['BF_ZLIB_LIB'],
169                 lenv['BF_LIBSAMPLERATE_LIB']
170                 ]
171
172         syslibs += Split(lenv['BF_FREETYPE_LIB'])
173         if lenv['WITH_BF_PYTHON'] and not lenv['WITH_BF_STATICPYTHON']:
174                 if lenv['BF_DEBUG'] and lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc', 'win32-mingw'):
175                         syslibs.append(lenv['BF_PYTHON_LIB']+'_d')
176                 else:
177                         syslibs.append(lenv['BF_PYTHON_LIB'])
178         if lenv['WITH_BF_INTERNATIONAL']:
179                 syslibs += Split(lenv['BF_GETTEXT_LIB'])
180         if lenv['WITH_BF_OPENAL']:
181                 if not lenv['WITH_BF_STATICOPENAL']:
182                         syslibs += Split(lenv['BF_OPENAL_LIB'])
183         if lenv['WITH_BF_OPENMP'] and lenv['CC'] != 'icc':
184                 if lenv['CC'] == 'cl.exe':
185                         syslibs += ['vcomp']
186                 else:
187                         syslibs += ['gomp']
188         if lenv['WITH_BF_ICONV']:
189                 syslibs += Split(lenv['BF_ICONV_LIB'])
190         if lenv['WITH_BF_OPENEXR']:
191                 if not lenv['WITH_BF_STATICOPENEXR']:
192                         syslibs += Split(lenv['BF_OPENEXR_LIB'])
193         if lenv['WITH_BF_FFMPEG']:
194                 syslibs += Split(lenv['BF_FFMPEG_LIB'])
195                 if lenv['WITH_BF_OGG']:
196                         syslibs += Split(lenv['BF_OGG_LIB'])
197         if lenv['WITH_BF_JACK']:
198                         syslibs += Split(lenv['BF_JACK_LIB'])
199         if lenv['WITH_BF_SNDFILE']:
200                         syslibs += Split(lenv['BF_SNDFILE_LIB'])
201         if lenv['WITH_BF_FFTW3']:
202                 syslibs += Split(lenv['BF_FFTW3_LIB'])
203         if lenv['WITH_BF_SDL']:
204                 syslibs += Split(lenv['BF_SDL_LIB'])
205         if not lenv['WITH_BF_STATICOPENGL']:
206                 syslibs += Split(lenv['BF_OPENGL_LIB'])
207         if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw','linuxcross', 'win64-vc'):
208                 syslibs += Split(lenv['BF_PTHREADS_LIB'])
209         if lenv['WITH_BF_LCMS']:
210                 syslibs.append(lenv['BF_LCMS_LIB'])
211
212
213         syslibs += lenv['LLIBS']
214
215         return syslibs
216
217 def propose_priorities():
218         print bc.OKBLUE+"Priorities:"+bc.ENDC
219         for t in possible_types:
220                 print bc.OKGREEN+"\t"+t+bc.ENDC
221                 new_priority = 0
222                 curlib = libs[t]
223                 sortlist = curlib.keys()
224                 sortlist.sort()
225
226                 for sk in sortlist:
227                         v = curlib[sk]
228                         #for p,v in sorted(libs[t].iteritems()):
229                         print "\t\t",new_priority, v
230                         new_priority += 5
231
232 ## TODO: see if this can be made in an emitter
233 def buildinfo(lenv, build_type):
234         """
235         Generate a buildinfo object
236         """
237         build_date = time.strftime ("%Y-%m-%d")
238         build_time = time.strftime ("%H:%M:%S")
239         build_rev = os.popen('svnversion').read()[:-1] # remove \n
240
241         obj = []
242         if lenv['BF_BUILDINFO']:
243                 if sys.platform=='win32':
244                         build_info_file = open("source/creator/winbuildinfo.h", 'w')
245                         build_info_file.write("char *build_date=\"%s\";\n"%build_date)
246                         build_info_file.write("char *build_time=\"%s\";\n"%build_time)
247                         build_info_file.write("char *build_rev=\"%s\";\n"%build_rev)
248                         build_info_file.write("char *build_platform=\"win32\";\n")
249                         build_info_file.write("char *build_type=\"dynamic\";\n")
250                         build_info_file.close()
251                         lenv.Append (CPPDEFINES = ['NAN_BUILDINFO', 'BUILD_DATE'])
252                 else:
253                         lenv.Append (CPPDEFINES = ['BUILD_TIME=\'"%s"\''%(build_time),
254                                                                                 'BUILD_DATE=\'"%s"\''%(build_date),
255                                                                                 'BUILD_TYPE=\'"dynamic"\'',
256                                                                                 'BUILD_REV=\'"%s"\''%(build_rev),
257                                                                                 'NAN_BUILDINFO',
258                                                                                 'BUILD_PLATFORM=\'"%s"\''%(sys.platform)])
259                 obj = [lenv.Object (root_build_dir+'source/creator/%s_buildinfo'%build_type,
260                                                 [root_build_dir+'source/creator/buildinfo.c'])]
261         return obj
262
263 ##### END LIB STUFF ############
264
265 ##### ACTION STUFF #############
266
267 def my_compile_print(target, source, env):
268         a = '%s' % (source[0])
269         d, f = os.path.split(a)
270         return bc.OKBLUE+"Compiling"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
271
272 def my_moc_print(target, source, env):
273         a = '%s' % (source[0])
274         d, f = os.path.split(a)
275         return bc.OKBLUE+"Creating MOC"+bc.ENDC+ " ==> '"+bc.OKGREEN+"%s" %(f) + "'"+bc.ENDC
276
277 def my_linking_print(target, source, env):
278         t = '%s' % (target[0])
279         d, f = os.path.split(t)
280         return bc.OKBLUE+"Linking library"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
281
282 def my_program_print(target, source, env):
283         t = '%s' % (target[0])
284         d, f = os.path.split(t)
285         return bc.OKBLUE+"Linking program"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
286
287 def msvc_hack(env):
288         static_lib = SCons.Tool.createStaticLibBuilder(env)
289         program = SCons.Tool.createProgBuilder(env)
290         
291         env['BUILDERS']['Library'] = static_lib
292         env['BUILDERS']['StaticLibrary'] = static_lib
293         env['BUILDERS']['Program'] = program
294                 
295 def set_quiet_output(env):
296         mycaction = Action("$CCCOM", strfunction=my_compile_print)
297         myshcaction = Action("$SHCCCOM", strfunction=my_compile_print)
298         mycppaction = Action("$CXXCOM", strfunction=my_compile_print)
299         myshcppaction = Action("$SHCXXCOM", strfunction=my_compile_print)
300         mylibaction = Action("$ARCOM", strfunction=my_linking_print)
301         mylinkaction = Action("$LINKCOM", strfunction=my_program_print)
302
303         static_ob, shared_ob = SCons.Tool.createObjBuilders(env)
304         static_ob.add_action('.c', mycaction)
305         static_ob.add_action('.cpp', mycppaction)
306         shared_ob.add_action('.c', myshcaction)
307         shared_ob.add_action('.cpp', myshcppaction)
308
309         static_lib = SCons.Builder.Builder(action = mylibaction,
310                                                                            emitter = '$LIBEMITTER',
311                                                                            prefix = '$LIBPREFIX',
312                                                                            suffix = '$LIBSUFFIX',
313                                                                            src_suffix = '$OBJSUFFIX',
314                                                                            src_builder = 'StaticObject')
315
316         program = SCons.Builder.Builder(action = mylinkaction,
317                                                                         emitter = '$PROGEMITTER',
318                                                                         prefix = '$PROGPREFIX',
319                                                                         suffix = '$PROGSUFFIX',
320                                                                         src_suffix = '$OBJSUFFIX',
321                                                                         src_builder = 'Object',
322                                                                         target_scanner = SCons.Defaults.ProgScan)
323
324         env['BUILDERS']['Object'] = static_ob
325         env['BUILDERS']['StaticObject'] = static_ob
326         env['BUILDERS']['StaticLibrary'] = static_lib
327         env['BUILDERS']['Library'] = static_lib
328         env['BUILDERS']['Program'] = program
329
330
331 def unzip_pybundle(from_zip,to_dir,exclude_re):
332         import zipfile
333         
334         zip= zipfile.ZipFile(from_zip, mode='r')
335         exclude_re= list(exclude_re) #single re object or list of re objects
336         debug= 0 #list files instead of unpacking
337         good= []
338         if debug: print '\nFiles not being unpacked:\n'
339         for name in zip.namelist():
340                 is_bad= 0
341                 for r in exclude_re:
342                         if r.match(name):
343                                 is_bad=1
344                                 if debug: print name
345                                 break
346                 if not is_bad:
347                         good.append(name)
348         if debug:
349                 print '\nFiles being unpacked:\n'
350                 for g in good:
351                         print g
352         else:
353                 zip.extractall(to_dir, good)
354
355 def my_winpybundle_print(target, source, env):
356         pass
357
358 def WinPyBundle(target=None, source=None, env=None):
359         import shutil, re
360         py_zip= env.subst( env['LCGDIR'] )
361         if py_zip[0]=='#':
362                 py_zip= py_zip[1:]
363         py_zip+= '/release/python' + env['BF_PYTHON_VERSION'].replace('.','') + '.zip'
364
365         py_target = env.subst( env['BF_INSTALLDIR'] )
366         if py_target[0]=='#':
367                 py_target=py_target[1:]
368         py_target+= '/.blender/python/lib/' 
369         def printexception(func,path,ex):
370                 if os.path.exists(path): #do not report if path does not exist. eg on a fresh build.
371                         print str(func) + ' failed on ' + str(path)
372         print "Trying to remove existing py bundle."
373         shutil.rmtree(py_target, False, printexception)
374         exclude_re=[re.compile('.*/test/.*'),
375                                 re.compile('^config/.*'),
376                                 re.compile('^distutils/.*'),
377                                 re.compile('^idlelib/.*'),
378                                 re.compile('^lib2to3/.*'),
379                                 re.compile('^tkinter/.*')]
380         print "Unpacking '" + py_zip + "' to '" + py_target + "'"
381         unzip_pybundle(py_zip,py_target,exclude_re)
382
383 def  my_appit_print(target, source, env):
384         a = '%s' % (target[0])
385         d, f = os.path.split(a)
386         return "making bundle for " + f
387
388 def AppIt(target=None, source=None, env=None):
389         import shutil
390         import commands
391         import os.path
392         
393         
394         a = '%s' % (target[0])
395         builddir, b = os.path.split(a)
396         libdir = env['LCGDIR'][1:]
397
398         bldroot = env.Dir('.').abspath
399         binary = env['BINARYKIND']
400          
401         if b=='verse':
402                 print bc.OKBLUE+"no bundle for verse"+bc.ENDC 
403                 return 0
404         
405         sourcedir = bldroot + '/source/darwin/%s.app'%binary
406         sourceinfo = bldroot + "/source/darwin/%s.app/Contents/Info.plist"%binary
407         targetinfo = builddir +'/' + "%s.app/Contents/Info.plist"%binary
408         cmd = builddir + '/' +'%s.app'%binary
409         
410         if os.path.isdir(cmd):
411                 shutil.rmtree(cmd)
412         shutil.copytree(sourcedir, cmd)
413         cmd = "cat %s | sed s/VERSION/`cat release/VERSION`/ | sed s/DATE/`date +'%%Y-%%b-%%d'`/ > %s"%(sourceinfo,targetinfo)
414         commands.getoutput(cmd)
415         cmd = 'cp %s/%s %s/%s.app/Contents/MacOS/%s'%(builddir, binary,builddir, binary, binary)
416         commands.getoutput(cmd)
417         cmd = 'mkdir %s/%s.app/Contents/MacOS/.blender/'%(builddir, binary)
418         print cmd
419         commands.getoutput(cmd)
420         cmd = builddir + '/%s.app/Contents/MacOS/.blender'%binary
421         shutil.copy(bldroot + '/bin/.blender/.bfont.ttf', cmd)
422         shutil.copy(bldroot + '/bin/.blender/.Blanguages', cmd)
423         cmd = 'cp -R %s/bin/.blender/locale %s/%s.app/Contents/Resources/'%(bldroot,builddir,binary)
424         commands.getoutput(cmd) 
425         cmd = 'cp -R %s/bin/.blender/locale %s/%s.app/Contents/MacOS/.blender/'%(bldroot,builddir,binary)
426         commands.getoutput(cmd) 
427         cmd = 'cp %s/bin/.blender/.Blanguages %s/%s.app/Contents/Resources/'%(bldroot,builddir,binary)
428         commands.getoutput(cmd) 
429         cmd = 'mkdir %s/%s.app/Contents/MacOS/.blender/python/'%(builddir,binary)
430         commands.getoutput(cmd) 
431         cmd = 'unzip -q %s/release/python.zip -d %s/%s.app/Contents/MacOS/.blender/python/'%(libdir,builddir,binary)
432         commands.getoutput(cmd) 
433         cmd = 'cp -R %s/release/scripts %s/%s.app/Contents/MacOS/.blender/'%(bldroot,builddir,binary)
434         commands.getoutput(cmd)
435         cmd = 'cp -R %s/release/ui %s/%s.app/Contents/MacOS/.blender/'%(bldroot,builddir,binary)
436         commands.getoutput(cmd)
437         cmd = 'cp -R %s/release/io %s/%s.app/Contents/MacOS/.blender/'%(bldroot,builddir,binary)
438         commands.getoutput(cmd)
439         cmd = 'chmod +x  %s/%s.app/Contents/MacOS/%s'%(builddir,binary, binary)
440         commands.getoutput(cmd)
441         cmd = 'find %s/%s.app -name .svn -prune -exec rm -rf {} \;'%(builddir, binary)
442         commands.getoutput(cmd)
443         cmd = 'find %s/%s.app -name .DS_Store -exec rm -rf {} \;'%(builddir, binary)
444         commands.getoutput(cmd)
445
446 # extract copy system python, be sure to update other build systems
447 # when making changes to the files that are copied.
448 def my_unixpybundle_print(target, source, env):
449         pass
450
451 def UnixPyBundle(target=None, source=None, env=None):
452         # Any Unix except osx
453         #-- .blender/python/lib/python3.1
454         
455         import commands
456         
457         def run(cmd):
458                 print 'Install command:', cmd
459                 commands.getoutput(cmd)
460         
461         if env['WITH_BF_FHS']:  dir = os.path.join(env['BF_INSTALLDIR'], 'share', 'blender', env['BF_VERSION']) # BLENDERPATH
462         else:                                   dir = os.path.join(env['BF_INSTALLDIR'], '.blender')
463         
464         py_src =        env.subst( env['BF_PYTHON_LIBPATH'] + '/python'+env['BF_PYTHON_VERSION'] )
465         py_target =     env.subst( dir + '/python/lib/python'+env['BF_PYTHON_VERSION'] )
466         
467         # Copied from source/creator/CMakeLists.txt, keep in sync.
468         print 'Install python from:'
469         print '\t"%s" into...' %        py_src
470         print '\t"%s"\n' %                      py_target
471         
472         run('rm -rf "%s"' % py_target)
473         try:    os.makedirs(os.path.dirname(py_target)) # the final part is copied
474         except:pass
475         
476         run('cp -R "%s" "%s"' % (py_src, os.path.dirname(py_target)))
477         run('rm -rf "%s/distutils"' % py_target)
478         run('rm -rf "%s/lib2to3"' % py_target)
479         run('rm -rf "%s/idlelib"' % py_target)
480         run('rm -rf "%s/tkinter"' % py_target)
481         run('rm -rf "%s/config"' % py_target)
482
483         run('rm -rf "%s/site-packages"' % py_target)
484         run('mkdir "%s/site-packages"' % py_target)    # python needs it.'
485
486         run('rm "%s/lib-dynload/_tkinter.so"' % py_target)
487         run('find "%s" -name "test" -prune -exec rm -rf {} \;' % py_target)
488         run('find "%s" -name "*.py?" -exec rm -rf {} \;' % py_target)
489         run('find "%s" -name "*.so"-exec strip -s {} \;' % py_target)
490
491 #### END ACTION STUFF #########
492
493 def bsc(env, target, source):
494         
495         bd = os.path.dirname(target[0].abspath)
496         bscfile = '\"'+target[0].abspath+'\"'
497         bscpathcollect = '\"'+bd + os.sep + '*.sbr\"'
498         bscpathtmp = '\"'+bd + os.sep + 'bscmake.tmp\"'
499
500         os.system('dir /b/s '+bscpathcollect+' >'+bscpathtmp)
501
502         myfile = open(bscpathtmp[1:-1], 'r')
503         lines = myfile.readlines()
504         myfile.close()
505
506         newfile = open(bscpathtmp[1:-1], 'w')
507         for l in lines:
508                 newfile.write('\"'+l[:-1]+'\"\n')
509         newfile.close()
510                                 
511         os.system('bscmake /nologo /n /o'+bscfile+' @'+bscpathtmp)
512         os.system('del '+bscpathtmp)
513
514 class BlenderEnvironment(SConsEnvironment):
515
516         def BlenderRes(self=None, libname=None, source=None, libtype=['core'], priority=[100]):
517                 global libs
518                 if not self or not libname or not source:
519                         print bc.FAIL+'Cannot continue.  Missing argument for BlenderRes '+libname+bc.ENDC
520                         self.Exit()
521                 if self['OURPLATFORM'] not in ('win32-vc','win32-mingw','linuxcross', 'win64-vc'):
522                         print bc.FAIL+'BlenderRes is for windows only!'+bc.END
523                         self.Exit()
524                 
525                 print bc.HEADER+'Configuring resource '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC
526                 lenv = self.Clone()
527                 if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
528                         res = lenv.RES('#'+root_build_dir+'lib/'+libname, source)
529                 else:
530                         res = lenv.RES(root_build_dir+'lib/'+libname, source)
531
532                 
533                 SConsEnvironment.Default(self, res)
534                 resources.append(res)
535
536         def BlenderLib(self=None, libname=None, sources=None, includes=[], defines=[], libtype='common', priority = 100, compileflags=None, cc_compileflags=None, cxx_compileflags=None):
537                 global vcp
538                 if not self or not libname or not sources:
539                         print bc.FAIL+'Cannot continue. Missing argument for BuildBlenderLib '+libname+bc.ENDC
540                         self.Exit()
541
542                 def list_substring(quickie, libname):
543                         for q in quickie:
544                                 if libname.find(q) != -1:
545                                         return True
546                         return False
547
548                 if list_substring(quickie, libname) or len(quickie)==0:
549                         if list_substring(quickdebug, libname):
550                                 print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname +bc.ENDC+bc.OKBLUE+ " (debug mode)" + bc.ENDC
551                         else:
552                                 print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname + bc.ENDC
553                         lenv = self.Clone()
554                         lenv.Append(CPPPATH=includes)
555                         lenv.Append(CPPDEFINES=defines)
556                         if lenv['BF_DEBUG'] or (libname in quickdebug):
557                                         lenv.Append(CFLAGS = lenv['BF_DEBUG_CFLAGS'])
558                                         lenv.Append(CCFLAGS = lenv['BF_DEBUG_CCFLAGS'])
559                                         lenv.Append(CXXFLAGS = lenv['BF_DEBUG_CXXFLAGS'])
560                         else:
561                                         lenv.Append(CFLAGS = lenv['REL_CFLAGS'])
562                                         lenv.Append(CCFLAGS = lenv['REL_CCFLAGS'])
563                                         lenv.Append(CXXFLAGS = lenv['REL_CXXFLAGS'])
564                         if lenv['BF_PROFILE']:
565                                         lenv.Append(CFLAGS = lenv['BF_PROFILE_CFLAGS'])
566                                         lenv.Append(CCFLAGS = lenv['BF_PROFILE_CCFLAGS'])
567                                         lenv.Append(CXXFLAGS = lenv['BF_PROFILE_CXXFLAGS'])
568                         if compileflags:
569                                 lenv.Replace(CFLAGS = compileflags)
570                         if cc_compileflags:
571                                 lenv.Replace(CCFLAGS = cc_compileflags)
572                         if cxx_compileflags:
573                                 lenv.Replace(CXXFLAGS = cxx_compileflags)
574                         lenv.Append(CFLAGS = lenv['C_WARN'])
575                         lenv.Append(CCFLAGS = lenv['CC_WARN'])
576                         lenv.Append(CXXFLAGS = lenv['CXX_WARN'])
577
578                         if lenv['OURPLATFORM'] == 'win64-vc':
579                                 lenv.Append(LINKFLAGS = ['/MACHINE:X64'])
580
581                         if lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
582                                 if lenv['BF_DEBUG']:
583                                         lenv.Append(CCFLAGS = ['/MTd'])
584                                 else:
585                                         lenv.Append(CCFLAGS = ['/MT'])
586                         
587                         targetdir = root_build_dir+'lib/' + libname
588                         if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
589                                 targetdir = '#'+targetdir
590                         lib = lenv.Library(target= targetdir, source=sources)
591                         SConsEnvironment.Default(self, lib) # we add to default target, because this way we get some kind of progress info during build
592                         if self['BF_MSVS'] and self['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
593                                 #if targetdir[0] == '#':
594                                 #       targetdir = targetdir[1:-1]
595                                 print "! ",targetdir+ '.vcproj' # + self['MSVSPROJECTSUFFIX']
596                                 vcproject = self.MSVSProject(target = targetdir + '.vcproj', # + self['MSVSPROJECTSUFFIX'],
597                                                  srcs = sources,
598                                                  buildtarget = lib,
599                                                  variant = 'Release',
600                                                  auto_build_solution=0)
601                                 vcp.append(vcproject)
602                                 SConsEnvironment.Default(self, vcproject)
603                 else:
604                         print bc.WARNING+'Not building '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC+' for '+bc.OKBLUE+'BF_QUICK'+bc.ENDC
605                 # note: libs is a global
606                 add_lib_to_dict(self, libs, libtype, libname, priority)
607
608         def BlenderProg(self=None, builddir=None, progname=None, sources=None, includes=None, libs=None, libpath=None, binarykind=''):
609                 global vcp
610                 print bc.HEADER+'Configuring program '+bc.ENDC+bc.OKGREEN+progname+bc.ENDC
611                 lenv = self.Clone()
612                 if lenv['OURPLATFORM'] in ('win32-vc', 'cygwin', 'win64-vc'):
613                         lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
614                         lenv.Append(LINKFLAGS = ['/FORCE:MULTIPLE'])
615                         if lenv['BF_DEBUG']:
616                                 lenv.Prepend(LINKFLAGS = ['/DEBUG','/PDB:'+progname+'.pdb'])
617                 if  lenv['OURPLATFORM']=='linux2':
618                         lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
619                         if lenv['WITH_BF_PYTHON']:
620                                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
621                 if  lenv['OURPLATFORM']=='sunos5':
622                         lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
623                         if lenv['WITH_BF_PYTHON']:
624                                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
625                         if lenv['CXX'].endswith('CC'):
626                                  lenv.Replace(LINK = '$CXX')
627                 if  lenv['OURPLATFORM']=='darwin':
628                         lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
629                         if lenv['WITH_BF_PYTHON']:
630                                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
631                         lenv.Append(LINKFLAGS = lenv['BF_OPENGL_LINKFLAGS'])
632                 if lenv['BF_PROFILE']:
633                         lenv.Append(LINKFLAGS = lenv['BF_PROFILE_LINKFLAGS'])
634                 lenv.Append(CPPPATH=includes)
635                 if root_build_dir[0]==os.sep or root_build_dir[1]==':':
636                         lenv.Append(LIBPATH=root_build_dir + '/lib')
637                 lenv.Append(LIBPATH=libpath)
638                 lenv.Append(LIBS=libs)
639                 if lenv['WITH_BF_QUICKTIME']:
640                          lenv.Append(LIBS = lenv['BF_QUICKTIME_LIB'])
641                          lenv.Append(LIBPATH = lenv['BF_QUICKTIME_LIBPATH'])
642                 prog = lenv.Program(target=builddir+'bin/'+progname, source=sources)
643                 if lenv['BF_DEBUG'] and lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc') and lenv['BF_BSC']:
644                         f = lenv.File(progname + '.bsc', builddir)
645                         brs = lenv.Command(f, prog, [bsc])
646                         SConsEnvironment.Default(self, brs)
647                 SConsEnvironment.Default(self, prog)
648                 if self['BF_MSVS'] and self['OURPLATFORM'] in ('win32-vc', 'win64-vc') and progname == 'blender':
649                         print "! ",builddir + "/" + progname + '.sln'
650                         sln = self.MSVSProject(target = builddir + "/" + progname + '.sln',
651                                          projects= vcp,
652                                          variant = 'Release')
653                         SConsEnvironment.Default(self, sln)
654                 program_list.append(prog)
655                 if  lenv['OURPLATFORM']=='darwin':
656                         lenv['BINARYKIND'] = binarykind
657                         lenv.AddPostAction(prog,Action(AppIt,strfunction=my_appit_print))
658                 elif os.sep == '/': # any unix
659                         if lenv['WITH_BF_PYTHON']:
660                                 if not lenv['WITHOUT_BF_INSTALL'] and not lenv['WITHOUT_BF_PYTHON_INSTALL']:
661                                         lenv.AddPostAction(prog,Action(UnixPyBundle,strfunction=my_unixpybundle_print))
662                 elif lenv['OURPLATFORM'].startswith('win'): # windows
663                         if lenv['WITH_BF_PYTHON']:
664                                 if not lenv['WITHOUT_BF_PYTHON_INSTALL']:
665                                         lenv.AddPostAction(prog,Action(WinPyBundle,strfunction=my_winpybundle_print))
666                 return prog
667
668         def Glob(lenv, pattern):
669                 path = string.replace(GetBuildPath(lenv,'SConscript'),'SConscript', '')
670                 files = []
671                 for i in glob.glob(path + pattern):
672                         files.append(string.replace(i, path, ''))
673                 return files