Fix #19574: winbuildinfo.h error when compiling with cmake on windows. I've now remov...
[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 import zipfile
24 import shutil
25 import cStringIO
26
27 from SCons.Script.SConscript import SConsEnvironment
28 import SCons.Action
29 import SCons.Util
30 import SCons.Builder
31 import SCons.Tool
32 import bcolors
33 bc = bcolors.bcolors()
34
35 Split = SCons.Util.Split
36 Action = SCons.Action.Action
37 Builder = SCons.Builder.Builder
38 GetBuildPath = SConsEnvironment.GetBuildPath
39
40 # a few globals
41 root_build_dir = ''
42 doc_build_dir = ''
43 quickie = None # Anything else than None if BF_QUICK has been passed
44 quicklist = [] # The list of libraries/programs to compile during a quickie
45 program_list = [] # A list holding Nodes to final binaries, used to create installs
46 arguments = None
47 targets = None
48 resources = []
49
50 #some internals
51 blenderdeps = [] # don't manipulate this one outside this module!
52
53 ##### LIB STUFF ##########
54
55 possible_types = ['core'] # can be set in ie. SConstruct
56 libs = {}
57 vcp = []
58
59 def getresources():
60         return resources
61
62 def init_lib_dict():
63         for pt in possible_types:
64                 libs[pt] = {}
65
66 # helper func for add_lib_to_dict
67 def internal_lib_to_dict(dict = None, libtype = None, libname = None, priority = 100):
68         if not libname in dict[libtype]:
69                 done = None
70                 while not done:
71                         if dict[libtype].has_key(priority):
72                                 priority = priority + 1
73                         else:
74                                 done = True
75                 dict[libtype][priority] = libname
76
77 # libtype and priority can both be lists, for defining lib in multiple places
78 def add_lib_to_dict(env, dict = None, libtype = None, libname = None, priority = 100):
79         if not dict or not libtype or not libname:
80                 print "Passed wrong arg"
81                 env.Exit()
82
83         if type(libtype) is str and type(priority) is int:
84                 internal_lib_to_dict(dict, libtype, libname, priority)
85         elif type(libtype) is list and type(priority) is list:
86                 if len(libtype)==len(priority):
87                         for lt, p in zip(libtype, priority):
88                                 internal_lib_to_dict(dict, lt, libname, p)
89                 else:
90                         print "libtype and priority lists are unequal in length"
91                         env.Exit()
92         else:
93                 print "Wrong type combinations for libtype and priority. Only str and int or list and list"
94                 env.Exit()
95
96 def create_blender_liblist(lenv = None, libtype = None):
97         if not lenv or not libtype:
98                 print "missing arg"
99
100         lst = []
101         if libtype in possible_types:
102                 curlib = libs[libtype]
103                 sortlist = curlib.keys()
104                 sortlist.sort()
105                 for sk in sortlist:
106                         v = curlib[sk]
107                         if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
108                                 target = os.path.abspath(os.getcwd() + os.sep + root_build_dir + 'lib' + os.sep +lenv['LIBPREFIX'] + v + lenv['LIBSUFFIX'])
109                         else:
110                                 target = os.path.abspath(root_build_dir + 'lib' + os.sep +lenv['LIBPREFIX'] + v + lenv['LIBSUFFIX'])
111                         lst.append(target)
112
113         return lst
114
115 ## TODO: static linking
116 def setup_staticlibs(lenv):
117         statlibs = [
118                 #here libs for static linking
119         ]
120         libincs = [
121                 '/usr/lib',
122                 lenv['BF_OPENGL_LIBPATH'],
123                 lenv['BF_JPEG_LIBPATH'],
124                 lenv['BF_PNG_LIBPATH'],
125                 lenv['BF_ZLIB_LIBPATH'],
126                 lenv['BF_LIBSAMPLERATE_LIBPATH'],
127                 lenv['BF_ICONV_LIBPATH']
128                 ]
129
130         libincs += Split(lenv['BF_FREETYPE_LIBPATH'])
131         if lenv['WITH_BF_PYTHON']:
132                 libincs += Split(lenv['BF_PYTHON_LIBPATH'])
133         if lenv['WITH_BF_SDL']:
134                 libincs += Split(lenv['BF_SDL_LIBPATH'])
135         if lenv['WITH_BF_FFMPEG']:
136                 libincs += Split(lenv['BF_FFMPEG_LIBPATH'])
137         if lenv['WITH_BF_JACK']:
138                 libincs += Split(lenv['BF_JACK_LIBPATH'])
139         if lenv['WITH_BF_SNDFILE']:
140                 libincs += Split(lenv['BF_SNDFILE_LIBPATH'])
141         if lenv['WITH_BF_OPENEXR']:
142                 libincs += Split(lenv['BF_OPENEXR_LIBPATH'])
143                 if lenv['WITH_BF_STATICOPENEXR']:
144                         statlibs += Split(lenv['BF_OPENEXR_LIB_STATIC'])
145         if lenv['WITH_BF_FFTW3']:
146                 libincs += Split(lenv['BF_FFTW3_LIBPATH'])
147         if lenv['WITH_BF_INTERNATIONAL']:
148                 libincs += Split(lenv['BF_GETTEXT_LIBPATH'])
149         if lenv['WITH_BF_OPENAL']:
150                 libincs += Split(lenv['BF_OPENAL_LIBPATH'])
151                 if lenv['WITH_BF_STATICOPENAL']:
152                         statlibs += Split(lenv['BF_OPENAL_LIB_STATIC'])
153         if lenv['WITH_BF_STATICOPENGL']:
154                 statlibs += Split(lenv['BF_OPENGL_LIB_STATIC'])
155         if lenv['WITH_BF_STATICCXX']:
156                 statlibs += Split(lenv['BF_CXX_LIB_STATIC'])
157
158         if lenv['WITH_BF_PYTHON'] and lenv['WITH_BF_STATICPYTHON']:
159                 statlibs += Split(lenv['BF_PYTHON_LIB_STATIC'])
160
161         if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
162                 libincs += Split(lenv['BF_PTHREADS_LIBPATH'])
163
164         return statlibs, libincs
165
166 def setup_syslibs(lenv):
167         syslibs = [
168                 
169                 lenv['BF_JPEG_LIB'],
170                 lenv['BF_PNG_LIB'],
171                 lenv['BF_ZLIB_LIB'],
172                 lenv['BF_LIBSAMPLERATE_LIB']
173                 ]
174
175         syslibs += Split(lenv['BF_FREETYPE_LIB'])
176         if lenv['WITH_BF_PYTHON'] and not lenv['WITH_BF_STATICPYTHON']:
177                 if lenv['BF_DEBUG'] and lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc', 'win32-mingw'):
178                         syslibs.append(lenv['BF_PYTHON_LIB']+'_d')
179                 else:
180                         syslibs.append(lenv['BF_PYTHON_LIB'])
181         if lenv['WITH_BF_INTERNATIONAL']:
182                 syslibs += Split(lenv['BF_GETTEXT_LIB'])
183         if lenv['WITH_BF_OPENAL']:
184                 if not lenv['WITH_BF_STATICOPENAL']:
185                         syslibs += Split(lenv['BF_OPENAL_LIB'])
186         if lenv['WITH_BF_OPENMP'] and lenv['CC'] != 'icc':
187                 if lenv['CC'] == 'cl.exe':
188                         syslibs += ['vcomp']
189                 else:
190                         syslibs += ['gomp']
191         if lenv['WITH_BF_ICONV']:
192                 syslibs += Split(lenv['BF_ICONV_LIB'])
193         if lenv['WITH_BF_OPENEXR']:
194                 if not lenv['WITH_BF_STATICOPENEXR']:
195                         syslibs += Split(lenv['BF_OPENEXR_LIB'])
196         if lenv['WITH_BF_FFMPEG']:
197                 syslibs += Split(lenv['BF_FFMPEG_LIB'])
198                 if lenv['WITH_BF_OGG']:
199                         syslibs += Split(lenv['BF_OGG_LIB'])
200         if lenv['WITH_BF_JACK']:
201                         syslibs += Split(lenv['BF_JACK_LIB'])
202         if lenv['WITH_BF_SNDFILE']:
203                         syslibs += Split(lenv['BF_SNDFILE_LIB'])
204         if lenv['WITH_BF_FFTW3']:
205                 syslibs += Split(lenv['BF_FFTW3_LIB'])
206         if lenv['WITH_BF_SDL']:
207                 syslibs += Split(lenv['BF_SDL_LIB'])
208         if not lenv['WITH_BF_STATICOPENGL']:
209                 syslibs += Split(lenv['BF_OPENGL_LIB'])
210         if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw','linuxcross', 'win64-vc'):
211                 syslibs += Split(lenv['BF_PTHREADS_LIB'])
212         if lenv['WITH_BF_LCMS']:
213                 syslibs.append(lenv['BF_LCMS_LIB'])
214
215
216         syslibs += lenv['LLIBS']
217
218         return syslibs
219
220 def propose_priorities():
221         print bc.OKBLUE+"Priorities:"+bc.ENDC
222         for t in possible_types:
223                 print bc.OKGREEN+"\t"+t+bc.ENDC
224                 new_priority = 0
225                 curlib = libs[t]
226                 sortlist = curlib.keys()
227                 sortlist.sort()
228
229                 for sk in sortlist:
230                         v = curlib[sk]
231                         #for p,v in sorted(libs[t].iteritems()):
232                         print "\t\t",new_priority, v
233                         new_priority += 5
234
235 ## TODO: see if this can be made in an emitter
236 def buildinfo(lenv, build_type):
237         """
238         Generate a buildinfo object
239         """
240         build_date = time.strftime ("%Y-%m-%d")
241         build_time = time.strftime ("%H:%M:%S")
242         build_rev = os.popen('svnversion').read()[:-1] # remove \n
243
244         obj = []
245         if lenv['BF_BUILDINFO']:
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         
324 class CompZipFile(zipfile.ZipFile):
325         """Partial copy of python2.6's zipfile.ZipFile (see http://www.python.org)
326         to get a extractall() that works on py2.5 and probably earlier distributions."""
327         def __init__(self, file, mode="r", compression=zipfile.ZIP_STORED, allowZip64=False):
328                 zipfile.ZipFile.__init__(self, file, mode, compression, allowZip64)
329                 if not hasattr(self,"extractall"): # use our method 
330                         print "Debug: Using comp_extractall!"
331                         self.extractall= self.comp_extractall
332
333         def comp_extractall(self, path=None, members=None, pwd=None): #renamed method
334                 """Extract all members from the archive to the current working
335                         directory. `path' specifies a different directory to extract to.
336                         `members' is optional and must be a subset of the list returned
337                         by namelist().
338                 """
339                 if members is None:
340                         members = self.namelist()
341
342                 for zipinfo in members:
343                         self.comp_extract(zipinfo, path, pwd) # use our method 
344
345         def comp_extract(self, member, path=None, pwd=None): #renamed method
346                 """Extract a member from the archive to the current working directory,
347                         using its full name. Its file information is extracted as accurately
348                         as possible. `member' may be a filename or a ZipInfo object. You can
349                         specify a different directory using `path'.
350                 """
351                 if not isinstance(member, zipfile.ZipInfo):
352                         member = self.getinfo(member)
353
354                 if path is None:
355                         path = os.getcwd()
356
357                 return self.comp_extract_member(member, path, pwd) # use our method 
358
359         def comp_extract_member(self, member, targetpath, pwd): #renamed method
360                 """Extract the ZipInfo object 'member' to a physical
361                         file on the path targetpath.
362                 """
363                 # build the destination pathname, replacing
364                 # forward slashes to platform specific separators.
365                 if targetpath[-1:] in (os.path.sep, os.path.altsep):
366                         targetpath = targetpath[:-1]
367
368                 # don't include leading "/" from file name if present
369                 if member.filename[0] == '/':
370                         targetpath = os.path.join(targetpath, member.filename[1:])
371                 else:
372                         targetpath = os.path.join(targetpath, member.filename)
373
374                 targetpath = os.path.normpath(targetpath)
375
376                 # Create all upper directories if necessary.
377                 upperdirs = os.path.dirname(targetpath)
378                 if upperdirs and not os.path.exists(upperdirs):
379                         os.makedirs(upperdirs)
380
381                 if member.filename[-1] == '/':
382                         os.mkdir(targetpath)
383                         return targetpath
384
385                 #use StrinIO instead so we don't have to reproduce more functionality.
386                 source = cStringIO.StringIO(self.read(member.filename))
387                 target = file(targetpath, "wb")
388                 shutil.copyfileobj(source, target)
389                 source.close()
390                 target.close()
391
392                 return targetpath
393
394 def unzip_pybundle(from_zip,to_dir,exclude_re):
395         
396         zip= CompZipFile(from_zip, mode='r')
397         exclude_re= list(exclude_re) #single re object or list of re objects
398         debug= 0 #list files instead of unpacking
399         good= []
400         if debug: print '\nFiles not being unpacked:\n'
401         for name in zip.namelist():
402                 is_bad= 0
403                 for r in exclude_re:
404                         if r.match(name):
405                                 is_bad=1
406                                 if debug: print name
407                                 break
408                 if not is_bad:
409                         good.append(name)
410         if debug:
411                 print '\nFiles being unpacked:\n'
412                 for g in good:
413                         print g
414         else:
415                 zip.extractall(to_dir, good)
416
417 def my_winpybundle_print(target, source, env):
418         pass
419
420 def WinPyBundle(target=None, source=None, env=None):
421         import re
422         py_zip= env.subst( env['LCGDIR'] )
423         if py_zip[0]=='#':
424                 py_zip= py_zip[1:]
425         py_zip+= '/release/python' + env['BF_PYTHON_VERSION'].replace('.','') + '.zip'
426
427         py_target = env.subst( env['BF_INSTALLDIR'] )
428         if py_target[0]=='#':
429                 py_target=py_target[1:]
430         py_target+= '/.blender/python/lib/' 
431         def printexception(func,path,ex):
432                 if os.path.exists(path): #do not report if path does not exist. eg on a fresh build.
433                         print str(func) + ' failed on ' + str(path)
434         print "Trying to remove existing py bundle."
435         shutil.rmtree(py_target, False, printexception)
436         exclude_re=[re.compile('.*/test/.*'),
437                                 re.compile('^config/.*'),
438                                 re.compile('^distutils/.*'),
439                                 re.compile('^idlelib/.*'),
440                                 re.compile('^lib2to3/.*'),
441                                 re.compile('^tkinter/.*')]
442         print "Unpacking '" + py_zip + "' to '" + py_target + "'"
443         unzip_pybundle(py_zip,py_target,exclude_re)
444
445 def  my_appit_print(target, source, env):
446         a = '%s' % (target[0])
447         d, f = os.path.split(a)
448         return "making bundle for " + f
449
450 def AppIt(target=None, source=None, env=None):
451         import shutil
452         import commands
453         import os.path
454         
455         
456         a = '%s' % (target[0])
457         builddir, b = os.path.split(a)
458         libdir = env['LCGDIR'][1:]
459
460         bldroot = env.Dir('.').abspath
461         binary = env['BINARYKIND']
462          
463         if b=='verse':
464                 print bc.OKBLUE+"no bundle for verse"+bc.ENDC 
465                 return 0
466         
467         sourcedir = bldroot + '/source/darwin/%s.app'%binary
468         sourceinfo = bldroot + "/source/darwin/%s.app/Contents/Info.plist"%binary
469         targetinfo = builddir +'/' + "%s.app/Contents/Info.plist"%binary
470         cmd = builddir + '/' +'%s.app'%binary
471         
472         if os.path.isdir(cmd):
473                 shutil.rmtree(cmd)
474         shutil.copytree(sourcedir, cmd)
475         cmd = "cat %s | sed s/VERSION/`cat release/VERSION`/ | sed s/DATE/`date +'%%Y-%%b-%%d'`/ > %s"%(sourceinfo,targetinfo)
476         commands.getoutput(cmd)
477         cmd = 'cp %s/%s %s/%s.app/Contents/MacOS/%s'%(builddir, binary,builddir, binary, binary)
478         commands.getoutput(cmd)
479         cmd = 'mkdir %s/%s.app/Contents/MacOS/.blender/'%(builddir, binary)
480         print cmd
481         commands.getoutput(cmd)
482         cmd = builddir + '/%s.app/Contents/MacOS/.blender'%binary
483         shutil.copy(bldroot + '/bin/.blender/.bfont.ttf', cmd)
484         shutil.copy(bldroot + '/bin/.blender/.Blanguages', cmd)
485         cmd = 'cp -R %s/bin/.blender/locale %s/%s.app/Contents/Resources/'%(bldroot,builddir,binary)
486         commands.getoutput(cmd) 
487         cmd = 'cp -R %s/bin/.blender/locale %s/%s.app/Contents/MacOS/.blender/'%(bldroot,builddir,binary)
488         commands.getoutput(cmd) 
489         cmd = 'cp %s/bin/.blender/.Blanguages %s/%s.app/Contents/Resources/'%(bldroot,builddir,binary)
490         commands.getoutput(cmd) 
491         cmd = 'mkdir %s/%s.app/Contents/MacOS/.blender/python/'%(builddir,binary)
492         commands.getoutput(cmd) 
493         cmd = 'unzip -q %s/release/python.zip -d %s/%s.app/Contents/MacOS/.blender/python/'%(libdir,builddir,binary)
494         commands.getoutput(cmd) 
495         cmd = 'cp -R %s/release/scripts %s/%s.app/Contents/MacOS/.blender/'%(bldroot,builddir,binary)
496         commands.getoutput(cmd)
497         cmd = 'cp -R %s/release/ui %s/%s.app/Contents/MacOS/.blender/'%(bldroot,builddir,binary)
498         commands.getoutput(cmd)
499         cmd = 'cp -R %s/release/io %s/%s.app/Contents/MacOS/.blender/'%(bldroot,builddir,binary)
500         commands.getoutput(cmd)
501         cmd = 'chmod +x  %s/%s.app/Contents/MacOS/%s'%(builddir,binary, binary)
502         commands.getoutput(cmd)
503         cmd = 'find %s/%s.app -name .svn -prune -exec rm -rf {} \;'%(builddir, binary)
504         commands.getoutput(cmd)
505         cmd = 'find %s/%s.app -name .DS_Store -exec rm -rf {} \;'%(builddir, binary)
506         commands.getoutput(cmd)
507
508 # extract copy system python, be sure to update other build systems
509 # when making changes to the files that are copied.
510 def my_unixpybundle_print(target, source, env):
511         pass
512
513 def UnixPyBundle(target=None, source=None, env=None):
514         # Any Unix except osx
515         #-- .blender/python/lib/python3.1
516         
517         import commands
518         
519         def run(cmd):
520                 print 'Install command:', cmd
521                 commands.getoutput(cmd)
522         
523         if env['WITH_BF_FHS']:  dir = os.path.join(env['BF_INSTALLDIR'], 'share', 'blender', env['BF_VERSION']) # BLENDERPATH
524         else:                                   dir = os.path.join(env['BF_INSTALLDIR'], '.blender')
525         
526         py_src =        env.subst( env['BF_PYTHON_LIBPATH'] + '/python'+env['BF_PYTHON_VERSION'] )
527         py_target =     env.subst( dir + '/python/lib/python'+env['BF_PYTHON_VERSION'] )
528         
529         # Copied from source/creator/CMakeLists.txt, keep in sync.
530         print 'Install python from:'
531         print '\t"%s" into...' %        py_src
532         print '\t"%s"\n' %                      py_target
533         
534         run('rm -rf "%s"' % py_target)
535         try:    os.makedirs(os.path.dirname(py_target)) # the final part is copied
536         except:pass
537         
538         run('cp -R "%s" "%s"' % (py_src, os.path.dirname(py_target)))
539         run('rm -rf "%s/distutils"' % py_target)
540         run('rm -rf "%s/lib2to3"' % py_target)
541         run('rm -rf "%s/idlelib"' % py_target)
542         run('rm -rf "%s/tkinter"' % py_target)
543         run('rm -rf "%s/config"' % py_target)
544
545         run('rm -rf "%s/site-packages"' % py_target)
546         run('mkdir "%s/site-packages"' % py_target)    # python needs it.'
547
548         run('rm -f "%s/lib-dynload/_tkinter.so"' % py_target)
549         run('find "%s" -name "test" -prune -exec rm -rf {} \;' % py_target)
550         run('find "%s" -name "*.py?" -exec rm -rf {} \;' % py_target)
551         run('find "%s" -name "*.so"-exec strip -s {} \;' % py_target)
552
553 #### END ACTION STUFF #########
554
555 def bsc(env, target, source):
556         
557         bd = os.path.dirname(target[0].abspath)
558         bscfile = '\"'+target[0].abspath+'\"'
559         bscpathcollect = '\"'+bd + os.sep + '*.sbr\"'
560         bscpathtmp = '\"'+bd + os.sep + 'bscmake.tmp\"'
561
562         os.system('dir /b/s '+bscpathcollect+' >'+bscpathtmp)
563
564         myfile = open(bscpathtmp[1:-1], 'r')
565         lines = myfile.readlines()
566         myfile.close()
567
568         newfile = open(bscpathtmp[1:-1], 'w')
569         for l in lines:
570                 newfile.write('\"'+l[:-1]+'\"\n')
571         newfile.close()
572                                 
573         os.system('bscmake /nologo /n /o'+bscfile+' @'+bscpathtmp)
574         os.system('del '+bscpathtmp)
575
576 class BlenderEnvironment(SConsEnvironment):
577
578         def BlenderRes(self=None, libname=None, source=None, libtype=['core'], priority=[100]):
579                 global libs
580                 if not self or not libname or not source:
581                         print bc.FAIL+'Cannot continue.  Missing argument for BlenderRes '+libname+bc.ENDC
582                         self.Exit()
583                 if self['OURPLATFORM'] not in ('win32-vc','win32-mingw','linuxcross', 'win64-vc'):
584                         print bc.FAIL+'BlenderRes is for windows only!'+bc.END
585                         self.Exit()
586                 
587                 print bc.HEADER+'Configuring resource '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC
588                 lenv = self.Clone()
589                 if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
590                         res = lenv.RES('#'+root_build_dir+'lib/'+libname, source)
591                 else:
592                         res = lenv.RES(root_build_dir+'lib/'+libname, source)
593
594                 
595                 SConsEnvironment.Default(self, res)
596                 resources.append(res)
597
598         def BlenderLib(self=None, libname=None, sources=None, includes=[], defines=[], libtype='common', priority = 100, compileflags=None, cc_compileflags=None, cxx_compileflags=None):
599                 global vcp
600                 if not self or not libname or not sources:
601                         print bc.FAIL+'Cannot continue. Missing argument for BuildBlenderLib '+libname+bc.ENDC
602                         self.Exit()
603
604                 def list_substring(quickie, libname):
605                         for q in quickie:
606                                 if libname.find(q) != -1:
607                                         return True
608                         return False
609
610                 if list_substring(quickie, libname) or len(quickie)==0:
611                         if list_substring(quickdebug, libname):
612                                 print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname +bc.ENDC+bc.OKBLUE+ " (debug mode)" + bc.ENDC
613                         else:
614                                 print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname + bc.ENDC
615                         lenv = self.Clone()
616                         lenv.Append(CPPPATH=includes)
617                         lenv.Append(CPPDEFINES=defines)
618                         if lenv['BF_DEBUG'] or (libname in quickdebug):
619                                         lenv.Append(CFLAGS = lenv['BF_DEBUG_CFLAGS'])
620                                         lenv.Append(CCFLAGS = lenv['BF_DEBUG_CCFLAGS'])
621                                         lenv.Append(CXXFLAGS = lenv['BF_DEBUG_CXXFLAGS'])
622                         else:
623                                         lenv.Append(CFLAGS = lenv['REL_CFLAGS'])
624                                         lenv.Append(CCFLAGS = lenv['REL_CCFLAGS'])
625                                         lenv.Append(CXXFLAGS = lenv['REL_CXXFLAGS'])
626                         if lenv['BF_PROFILE']:
627                                         lenv.Append(CFLAGS = lenv['BF_PROFILE_CFLAGS'])
628                                         lenv.Append(CCFLAGS = lenv['BF_PROFILE_CCFLAGS'])
629                                         lenv.Append(CXXFLAGS = lenv['BF_PROFILE_CXXFLAGS'])
630                         if compileflags:
631                                 lenv.Replace(CFLAGS = compileflags)
632                         if cc_compileflags:
633                                 lenv.Replace(CCFLAGS = cc_compileflags)
634                         if cxx_compileflags:
635                                 lenv.Replace(CXXFLAGS = cxx_compileflags)
636                         lenv.Append(CFLAGS = lenv['C_WARN'])
637                         lenv.Append(CCFLAGS = lenv['CC_WARN'])
638                         lenv.Append(CXXFLAGS = lenv['CXX_WARN'])
639
640                         if lenv['OURPLATFORM'] == 'win64-vc':
641                                 lenv.Append(LINKFLAGS = ['/MACHINE:X64'])
642
643                         if lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
644                                 if lenv['BF_DEBUG']:
645                                         lenv.Append(CCFLAGS = ['/MTd'])
646                                 else:
647                                         lenv.Append(CCFLAGS = ['/MT'])
648                         
649                         targetdir = root_build_dir+'lib/' + libname
650                         if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
651                                 targetdir = '#'+targetdir
652                         lib = lenv.Library(target= targetdir, source=sources)
653                         SConsEnvironment.Default(self, lib) # we add to default target, because this way we get some kind of progress info during build
654                         if self['BF_MSVS'] and self['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
655                                 #if targetdir[0] == '#':
656                                 #       targetdir = targetdir[1:-1]
657                                 print "! ",targetdir+ '.vcproj' # + self['MSVSPROJECTSUFFIX']
658                                 vcproject = self.MSVSProject(target = targetdir + '.vcproj', # + self['MSVSPROJECTSUFFIX'],
659                                                  srcs = sources,
660                                                  buildtarget = lib,
661                                                  variant = 'Release',
662                                                  auto_build_solution=0)
663                                 vcp.append(vcproject)
664                                 SConsEnvironment.Default(self, vcproject)
665                 else:
666                         print bc.WARNING+'Not building '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC+' for '+bc.OKBLUE+'BF_QUICK'+bc.ENDC
667                 # note: libs is a global
668                 add_lib_to_dict(self, libs, libtype, libname, priority)
669
670         def BlenderProg(self=None, builddir=None, progname=None, sources=None, includes=None, libs=None, libpath=None, binarykind=''):
671                 global vcp
672                 print bc.HEADER+'Configuring program '+bc.ENDC+bc.OKGREEN+progname+bc.ENDC
673                 lenv = self.Clone()
674                 if lenv['OURPLATFORM'] in ('win32-vc', 'cygwin', 'win64-vc'):
675                         lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
676                         lenv.Append(LINKFLAGS = ['/FORCE:MULTIPLE'])
677                         if lenv['BF_DEBUG']:
678                                 lenv.Prepend(LINKFLAGS = ['/DEBUG','/PDB:'+progname+'.pdb'])
679                 if  lenv['OURPLATFORM']=='linux2':
680                         lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
681                         if lenv['WITH_BF_PYTHON']:
682                                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
683                 if  lenv['OURPLATFORM']=='sunos5':
684                         lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
685                         if lenv['WITH_BF_PYTHON']:
686                                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
687                         if lenv['CXX'].endswith('CC'):
688                                  lenv.Replace(LINK = '$CXX')
689                 if  lenv['OURPLATFORM']=='darwin':
690                         lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
691                         if lenv['WITH_BF_PYTHON']:
692                                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
693                         lenv.Append(LINKFLAGS = lenv['BF_OPENGL_LINKFLAGS'])
694                 if lenv['BF_PROFILE']:
695                         lenv.Append(LINKFLAGS = lenv['BF_PROFILE_LINKFLAGS'])
696                 lenv.Append(CPPPATH=includes)
697                 if root_build_dir[0]==os.sep or root_build_dir[1]==':':
698                         lenv.Append(LIBPATH=root_build_dir + '/lib')
699                 lenv.Append(LIBPATH=libpath)
700                 lenv.Append(LIBS=libs)
701                 if lenv['WITH_BF_QUICKTIME']:
702                          lenv.Append(LIBS = lenv['BF_QUICKTIME_LIB'])
703                          lenv.Append(LIBPATH = lenv['BF_QUICKTIME_LIBPATH'])
704                 prog = lenv.Program(target=builddir+'bin/'+progname, source=sources)
705                 if lenv['BF_DEBUG'] and lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc') and lenv['BF_BSC']:
706                         f = lenv.File(progname + '.bsc', builddir)
707                         brs = lenv.Command(f, prog, [bsc])
708                         SConsEnvironment.Default(self, brs)
709                 SConsEnvironment.Default(self, prog)
710                 if self['BF_MSVS'] and self['OURPLATFORM'] in ('win32-vc', 'win64-vc') and progname == 'blender':
711                         print "! ",builddir + "/" + progname + '.sln'
712                         sln = self.MSVSProject(target = builddir + "/" + progname + '.sln',
713                                          projects= vcp,
714                                          variant = 'Release')
715                         SConsEnvironment.Default(self, sln)
716                 program_list.append(prog)
717                 if  lenv['OURPLATFORM']=='darwin':
718                         lenv['BINARYKIND'] = binarykind
719                         lenv.AddPostAction(prog,Action(AppIt,strfunction=my_appit_print))
720                 elif os.sep == '/': # any unix
721                         if lenv['WITH_BF_PYTHON']:
722                                 if not lenv['WITHOUT_BF_INSTALL'] and not lenv['WITHOUT_BF_PYTHON_INSTALL']:
723                                         lenv.AddPostAction(prog,Action(UnixPyBundle,strfunction=my_unixpybundle_print))
724                 elif lenv['OURPLATFORM'].startswith('win'): # windows
725                         if lenv['WITH_BF_PYTHON']:
726                                 if not lenv['WITHOUT_BF_PYTHON_INSTALL']:
727                                         lenv.AddPostAction(prog,Action(WinPyBundle,strfunction=my_winpybundle_print))
728                 return prog
729
730         def Glob(lenv, pattern):
731                 path = string.replace(GetBuildPath(lenv,'SConscript'),'SConscript', '')
732                 files = []
733                 for i in glob.glob(path + pattern):
734                         files.append(string.replace(i, path, ''))
735                 return files