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