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