Merging r38036 through r38196 from trunk into soc-2011-tomato
[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_TIFF']:
152         libincs += Split(lenv['BF_TIFF_LIBPATH'])
153         if lenv['WITH_BF_STATICTIFF']:
154             statlibs += Split(lenv['BF_TIFF_LIB_STATIC'])
155     if lenv['WITH_BF_ZLIB'] and lenv['WITH_BF_STATICZLIB']:
156         statlibs += Split(lenv['BF_ZLIB_LIB_STATIC'])
157     if lenv['WITH_BF_FFTW3']:
158         libincs += Split(lenv['BF_FFTW3_LIBPATH'])
159         if lenv['WITH_BF_STATICFFTW3']:
160             statlibs += Split(lenv['BF_FFTW3_LIB_STATIC'])
161     if lenv['WITH_BF_FFMPEG'] and lenv['WITH_BF_STATICFFMPEG']:
162         statlibs += Split(lenv['BF_FFMPEG_LIB_STATIC'])
163     if lenv['WITH_BF_INTERNATIONAL']:
164         libincs += Split(lenv['BF_GETTEXT_LIBPATH'])
165         if lenv['WITH_BF_GETTEXT_STATIC']:
166             statlibs += Split(lenv['BF_GETTEXT_LIB_STATIC'])
167         if lenv['WITH_BF_FREETYPE_STATIC']:
168             statlibs += Split(lenv['BF_FREETYPE_LIB_STATIC'])
169     if lenv['WITH_BF_OPENAL']:
170         libincs += Split(lenv['BF_OPENAL_LIBPATH'])
171         if lenv['WITH_BF_STATICOPENAL']:
172             statlibs += Split(lenv['BF_OPENAL_LIB_STATIC'])
173     if lenv['WITH_BF_STATICOPENGL']:
174         statlibs += Split(lenv['BF_OPENGL_LIB_STATIC'])
175     if lenv['WITH_BF_STATICCXX']:
176         statlibs += Split(lenv['BF_CXX_LIB_STATIC'])
177
178     if lenv['WITH_BF_PYTHON'] and lenv['WITH_BF_STATICPYTHON']:
179         statlibs += Split(lenv['BF_PYTHON_LIB_STATIC'])
180
181     if lenv['WITH_BF_SNDFILE'] and lenv['WITH_BF_STATICSNDFILE']:
182         statlibs += Split(lenv['BF_SNDFILE_LIB_STATIC'])
183
184     if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
185         libincs += Split(lenv['BF_PTHREADS_LIBPATH'])
186
187     if lenv['WITH_BF_COLLADA']:
188         libincs += Split(lenv['BF_OPENCOLLADA_LIBPATH'])
189         if lenv['OURPLATFORM'] not in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
190             libincs += Split(lenv['BF_PCRE_LIBPATH'])
191             libincs += Split(lenv['BF_EXPAT_LIBPATH'])
192
193     if lenv['WITH_BF_OPENMP']:
194         if lenv['OURPLATFORM'] == 'linuxcross':
195             libincs += Split(lenv['BF_OPENMP_LIBPATH'])
196
197     if lenv['WITH_BF_STATICLIBSAMPLERATE']:
198         statlibs += Split(lenv['BF_LIBSAMPLERATE_LIB_STATIC'])
199
200     # setting this last so any overriding of manually libs could be handled
201     if lenv['OURPLATFORM'] not in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'):
202         libincs.append('/usr/lib')
203
204     if lenv['WITH_BF_JEMALLOC']:
205         libincs += Split(lenv['BF_JEMALLOC_LIBPATH'])
206         if lenv['WITH_BF_STATICJEMALLOC']:
207             statlibs += Split(lenv['BF_JEMALLOC_LIB_STATIC'])
208
209     return statlibs, libincs
210
211 def setup_syslibs(lenv):
212     syslibs = [
213         
214         lenv['BF_JPEG_LIB'],
215         lenv['BF_PNG_LIB'],
216         ]
217
218     if not lenv['WITH_BF_FREETYPE_STATIC']:
219         syslibs += Split(lenv['BF_FREETYPE_LIB'])
220     if lenv['WITH_BF_PYTHON'] and not lenv['WITH_BF_STATICPYTHON']:
221         if lenv['BF_DEBUG'] and lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc', 'win32-mingw'):
222             syslibs.append(lenv['BF_PYTHON_LIB']+'_d')
223         else:
224             syslibs.append(lenv['BF_PYTHON_LIB'])
225     if lenv['WITH_BF_INTERNATIONAL'] and not lenv['WITH_BF_GETTEXT_STATIC']:
226         syslibs += Split(lenv['BF_GETTEXT_LIB'])
227     if lenv['WITH_BF_OPENAL']:
228         if not lenv['WITH_BF_STATICOPENAL']:
229             syslibs += Split(lenv['BF_OPENAL_LIB'])
230     if lenv['WITH_BF_OPENMP'] and lenv['CC'] != 'icc':
231         if lenv['CC'] == 'cl.exe':
232             syslibs += ['vcomp']
233         else:
234             syslibs += ['gomp']
235     if lenv['WITH_BF_ICONV']:
236         syslibs += Split(lenv['BF_ICONV_LIB'])
237     if lenv['WITH_BF_OPENEXR'] and not lenv['WITH_BF_STATICOPENEXR']:
238         syslibs += Split(lenv['BF_OPENEXR_LIB'])
239     if lenv['WITH_BF_TIFF'] and not lenv['WITH_BF_STATICTIFF']:
240         syslibs += Split(lenv['BF_TIFF_LIB'])
241     if lenv['WITH_BF_ZLIB'] and not lenv['WITH_BF_STATICZLIB']:
242         syslibs += Split(lenv['BF_ZLIB_LIB'])
243     if lenv['WITH_BF_FFMPEG'] and not lenv['WITH_BF_STATICFFMPEG']:
244         syslibs += Split(lenv['BF_FFMPEG_LIB'])
245         if lenv['WITH_BF_OGG']:
246             syslibs += Split(lenv['BF_OGG_LIB'])
247     if lenv['WITH_BF_JACK']:
248             syslibs += Split(lenv['BF_JACK_LIB'])
249     if lenv['WITH_BF_SNDFILE'] and not lenv['WITH_BF_STATICSNDFILE']:
250             syslibs += Split(lenv['BF_SNDFILE_LIB'])
251     if lenv['WITH_BF_FFTW3'] and not lenv['WITH_BF_STATICFFTW3']:
252         syslibs += Split(lenv['BF_FFTW3_LIB'])
253     if lenv['WITH_BF_SDL']:
254         syslibs += Split(lenv['BF_SDL_LIB'])
255     if not lenv['WITH_BF_STATICOPENGL']:
256         syslibs += Split(lenv['BF_OPENGL_LIB'])
257     if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw','linuxcross', 'win64-vc'):
258         syslibs += Split(lenv['BF_PTHREADS_LIB'])
259     if lenv['WITH_BF_COLLADA']:
260         syslibs.append(lenv['BF_PCRE_LIB'])
261         if lenv['BF_DEBUG']:
262             syslibs += [colladalib+'_d' for colladalib in Split(lenv['BF_OPENCOLLADA_LIB'])]
263         else:
264             syslibs += Split(lenv['BF_OPENCOLLADA_LIB'])
265         syslibs.append(lenv['BF_EXPAT_LIB'])
266
267     if not lenv['WITH_BF_STATICLIBSAMPLERATE']:
268         syslibs += Split(lenv['BF_LIBSAMPLERATE_LIB'])
269
270     if lenv['WITH_BF_JEMALLOC']:
271         if not lenv['WITH_BF_STATICJEMALLOC']:
272             syslibs += Split(lenv['BF_JEMALLOC_LIB'])
273
274     syslibs += lenv['LLIBS']
275
276     return syslibs
277
278 def propose_priorities():
279     print bc.OKBLUE+"Priorities:"+bc.ENDC
280     for t in possible_types:
281         print bc.OKGREEN+"\t"+t+bc.ENDC
282         new_priority = 0
283         curlib = libs[t]
284         sortlist = curlib.keys()
285         sortlist.sort()
286
287         for sk in sortlist:
288             v = curlib[sk]
289             #for p,v in sorted(libs[t].iteritems()):
290             print "\t\t",new_priority, v
291             new_priority += 5
292
293 # emits the necessary file objects for creator.c, to be used in creating
294 # the final blender executable
295 def creator(env):
296     sources = ['creator.c']# + Blender.buildinfo(env, "dynamic") + Blender.resources
297
298     incs = ['#/intern/guardedalloc', '#/source/blender/blenlib', '#/source/blender/blenkernel', '#/source/blender/editors/include', '#/source/blender/blenloader', '#/source/blender/imbuf', '#/source/blender/renderconverter', '#/source/blender/render/extern/include', '#/source/blender/windowmanager', '#/source/blender/makesdna', '#/source/blender/makesrna', '#/source/gameengine/BlenderRoutines', '#/extern/glew/include', '#/source/blender/gpu', env['BF_OPENGL_INC']]
299
300     defs = []
301     if env['WITH_BF_QUICKTIME']:
302         incs.append(env['BF_QUICKTIME_INC'])
303         defs.append('WITH_QUICKTIME')
304
305     if env['WITH_BF_BINRELOC']:
306         incs.append('#/extern/binreloc/include')
307         defs.append('WITH_BINRELOC')
308
309     if env['WITH_BF_OPENEXR']:
310         defs.append('WITH_OPENEXR')
311
312     if env['WITH_BF_TIFF']:
313         defs.append('WITH_TIFF')
314
315     if not env['WITH_BF_SDL']:
316         defs.append('DISABLE_SDL')
317
318     if env['WITH_BF_PYTHON']:
319         incs.append('#/source/blender/python')
320         defs.append('WITH_PYTHON')
321         if env['BF_DEBUG']:
322             defs.append('_DEBUG')
323         
324     if env['BF_BUILDINFO']:
325         defs.append('BUILD_DATE')
326         defs.append('NAN_BUILDINFO')
327         
328     if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
329         incs.append(env['BF_PTHREADS_INC'])
330
331     env.Append(CPPDEFINES=defs)
332     env.Append(CPPPATH=incs)
333     obj = [env.Object(root_build_dir+'source/creator/creator/creator', ['#source/creator/creator.c'])]
334
335     return obj
336
337 ## TODO: see if this can be made in an emitter
338 def buildinfo(lenv, build_type):
339     """
340     Generate a buildinfo object
341     """
342     build_date = time.strftime ("%Y-%m-%d")
343     build_time = time.strftime ("%H:%M:%S")
344     build_rev = os.popen('svnversion').read()[:-1] # remove \n
345     if build_rev == '': 
346         build_rev = '-UNKNOWN-'
347     if lenv['BF_DEBUG']:
348         build_type = "Debug"
349         build_cflags = ' '.join(lenv['CFLAGS'] + lenv['CCFLAGS'] + lenv['BF_DEBUG_CCFLAGS'] + lenv['CPPFLAGS'])
350         build_cxxflags = ' '.join(lenv['CCFLAGS'] + lenv['CXXFLAGS'] + lenv['CPPFLAGS'])
351     else:
352         build_type = "Release"
353         build_cflags = ' '.join(lenv['CFLAGS'] + lenv['CCFLAGS'] + lenv['REL_CFLAGS'] + lenv['REL_CCFLAGS'] + lenv['CPPFLAGS'])
354         build_cxxflags = ' '.join(lenv['CCFLAGS'] + lenv['CXXFLAGS'] + lenv['REL_CXXFLAGS'] + lenv['REL_CCFLAGS'] + lenv['CPPFLAGS'])
355
356     build_linkflags = ' '.join(lenv['PLATFORM_LINKFLAGS'])
357
358     obj = []
359     if lenv['BF_BUILDINFO']:
360         lenv.Append (CPPDEFINES = ['BUILD_TIME="%s"'%(build_time),
361                                     'BUILD_DATE="%s"'%(build_date),
362                                     'BUILD_TYPE="%s"'%(build_type),
363                                     'BUILD_REV="%s"'%(build_rev),
364                                     'NAN_BUILDINFO',
365                                     'BUILD_PLATFORM="%s:%s"'%(platform.system(), platform.architecture()[0]),
366                                     'BUILD_CFLAGS=\\"%s\\"'%(build_cflags),
367                                     'BUILD_CXXFLAGS=\\"%s\\"'%(build_cxxflags),
368                                     'BUILD_LINKFLAGS=\\"%s\\"'%(build_linkflags),
369                                     'BUILD_SYSTEM="SCons"'
370                     ])
371
372         lenv.Append (CPPPATH = [root_build_dir+'source/blender/blenkernel'])
373
374         obj = [lenv.Object (root_build_dir+'source/creator/%s_buildinfo'%build_type, ['#source/creator/buildinfo.c'])]
375
376     return obj
377
378 ##### END LIB STUFF ############
379
380 ##### ACTION STUFF #############
381
382 def my_print_cmd_line(self, s, target, source, env):
383     sys.stdout.write(' ' * 70 + '\r')
384     sys.stdout.flush()
385     sys.stdout.write(s + "\r")
386     sys.stdout.flush()
387
388 def my_compile_print(target, source, env):
389     a = '%s' % (source[0])
390     d, f = os.path.split(a)
391     return bc.OKBLUE+"Compiling"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
392
393 def my_moc_print(target, source, env):
394     a = '%s' % (source[0])
395     d, f = os.path.split(a)
396     return bc.OKBLUE+"Creating MOC"+bc.ENDC+ " ==> '"+bc.OKGREEN+"%s" %(f) + "'"+bc.ENDC
397
398 def my_linking_print(target, source, env):
399     t = '%s' % (target[0])
400     d, f = os.path.split(t)
401     return bc.OKBLUE+"Linking library"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
402
403 def my_program_print(target, source, env):
404     t = '%s' % (target[0])
405     d, f = os.path.split(t)
406     return bc.OKBLUE+"Linking program"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
407
408 def msvc_hack(env):
409     static_lib = SCons.Tool.createStaticLibBuilder(env)
410     program = SCons.Tool.createProgBuilder(env)
411     
412     env['BUILDERS']['Library'] = static_lib
413     env['BUILDERS']['StaticLibrary'] = static_lib
414     env['BUILDERS']['Program'] = program
415         
416 def set_quiet_output(env):
417     mycaction = Action("$CCCOM", strfunction=my_compile_print)
418     myshcaction = Action("$SHCCCOM", strfunction=my_compile_print)
419     mycppaction = Action("$CXXCOM", strfunction=my_compile_print)
420     myshcppaction = Action("$SHCXXCOM", strfunction=my_compile_print)
421     mylibaction = Action("$ARCOM", strfunction=my_linking_print)
422     mylinkaction = Action("$LINKCOM", strfunction=my_program_print)
423
424     static_ob, shared_ob = SCons.Tool.createObjBuilders(env)
425     static_ob.add_action('.c', mycaction)
426     static_ob.add_action('.cpp', mycppaction)
427     shared_ob.add_action('.c', myshcaction)
428     shared_ob.add_action('.cpp', myshcppaction)
429
430     static_lib = SCons.Builder.Builder(action = mylibaction,
431                                        emitter = '$LIBEMITTER',
432                                        prefix = '$LIBPREFIX',
433                                        suffix = '$LIBSUFFIX',
434                                        src_suffix = '$OBJSUFFIX',
435                                        src_builder = 'StaticObject')
436
437     program = SCons.Builder.Builder(action = mylinkaction,
438                                     emitter = '$PROGEMITTER',
439                                     prefix = '$PROGPREFIX',
440                                     suffix = '$PROGSUFFIX',
441                                     src_suffix = '$OBJSUFFIX',
442                                     src_builder = 'Object',
443                                     target_scanner = SCons.Defaults.ProgScan)
444
445     env['BUILDERS']['Object'] = static_ob
446     env['BUILDERS']['StaticObject'] = static_ob
447     env['BUILDERS']['StaticLibrary'] = static_lib
448     env['BUILDERS']['Library'] = static_lib
449     env['BUILDERS']['Program'] = program
450     if env['BF_LINE_OVERWRITE']:
451         SCons.Action._ActionAction.print_cmd_line = my_print_cmd_line
452
453 def untar_pybundle(from_tar,to_dir,exclude_re):
454     tar= tarfile.open(from_tar, mode='r')
455     exclude_re= list(exclude_re) #single re object or list of re objects
456     debug= 0 #list files instead of unpacking
457     good= []
458     if debug: print '\nFiles not being unpacked:\n'
459     for name in tar.getnames():
460         is_bad= 0
461         for r in exclude_re:
462             if r.match(name):
463                 is_bad=1
464                 if debug: print name
465                 break
466         if not is_bad:
467             good.append(tar.getmember(name))
468     if debug:
469         print '\nFiles being unpacked:\n'
470         for g in good:
471             print g
472     else:
473         tar.extractall(to_dir, good)
474
475 def my_winpybundle_print(target, source, env):
476     pass
477
478 def WinPyBundle(target=None, source=None, env=None):
479     import re
480     py_tar= env.subst( env['LCGDIR'] )
481     if py_tar[0]=='#':
482         py_tar= py_tar[1:]
483     if env['BF_DEBUG']:
484         py_tar+= '/release/python' + env['BF_PYTHON_VERSION'].replace('.','') + '_d.tar.gz'
485     else:
486         py_tar+= '/release/python' + env['BF_PYTHON_VERSION'].replace('.','') + '.tar.gz'
487
488     py_target = env.subst( env['BF_INSTALLDIR'] )
489     if py_target[0]=='#':
490         py_target=py_target[1:]
491     py_target = os.path.join(py_target, VERSION, 'python', 'lib')
492     def printexception(func,path,ex):
493         if os.path.exists(path): #do not report if path does not exist. eg on a fresh build.
494             print str(func) + ' failed on ' + str(path)
495     print "Trying to remove existing py bundle."
496     shutil.rmtree(py_target, False, printexception)
497     exclude_re=[re.compile('.*/test/.*'),
498                 re.compile('^config/.*'),
499                 re.compile('^config-*/.*'),
500                 re.compile('^distutils/.*'),
501                 re.compile('^idlelib/.*'),
502                 re.compile('^lib2to3/.*'),
503                 re.compile('^tkinter/.*'),
504                 re.compile('^_tkinter_d.pyd'),
505                 re.compile('^turtledemo'),
506                 re.compile('^turtle.py'),
507                 ]
508
509     print "Unpacking '" + py_tar + "' to '" + py_target + "'"
510     untar_pybundle(py_tar,py_target,exclude_re)
511
512 def  my_appit_print(target, source, env):
513     a = '%s' % (target[0])
514     d, f = os.path.split(a)
515     return "making bundle for " + f
516
517 def AppIt(target=None, source=None, env=None):
518     import shutil
519     import commands
520     import os.path
521     
522     
523     a = '%s' % (target[0])
524     builddir, b = os.path.split(a)
525     libdir = env['LCGDIR'][1:]
526     osxarch = env['MACOSX_ARCHITECTURE']
527     installdir = env['BF_INSTALLDIR']
528     print("compiled architecture: %s"%(osxarch))
529     print("Installing to %s"%(installdir))
530     # TODO, use tar.
531     python_zip = 'python_' + osxarch + '.zip' # set specific python_arch.zip
532     print("unzipping to app-bundle: %s"%(python_zip))
533     bldroot = env.Dir('.').abspath
534     binary = env['BINARYKIND']
535      
536     if b=='verse':
537         print bc.OKBLUE+"no bundle for verse"+bc.ENDC 
538         return 0
539     
540     sourcedir = bldroot + '/source/darwin/%s.app'%binary
541     sourceinfo = bldroot + "/source/darwin/%s.app/Contents/Info.plist"%binary
542     targetinfo = installdir +'/' + "%s.app/Contents/Info.plist"%binary
543     cmd = installdir + '/' +'%s.app'%binary
544     
545     if os.path.isdir(cmd):
546         shutil.rmtree(cmd)
547     shutil.copytree(sourcedir, cmd)
548     cmd = "cat %s | sed s/\$\{MACOSX_BUNDLE_SHORT_VERSION_STRING\}/%s/ | "%(sourceinfo,VERSION)
549     cmd += "sed s/\$\{MACOSX_BUNDLE_LONG_VERSION_STRING\}/%s,\ %s/g > %s"%(VERSION,time.strftime("%Y-%b-%d"),targetinfo)
550     commands.getoutput(cmd)
551     cmd = 'cp %s/%s %s/%s.app/Contents/MacOS/%s'%(builddir, binary,installdir, binary, binary)
552     commands.getoutput(cmd)
553     cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/'%(installdir, binary, VERSION)
554 #    print cmd
555     commands.getoutput(cmd)
556     cmd = installdir + '/%s.app/Contents/MacOS/%s'%(binary,VERSION)
557     shutil.copy(bldroot + '/release/bin/.blender/.bfont.ttf', cmd)
558     shutil.copy(bldroot + '/release/bin/.blender/.Blanguages', cmd)
559     cmd = 'cp -R %s/release/bin/%s/locale %s/%s.app/Contents/Resources/'%(bldroot,VERSION,installdir,binary)
560     commands.getoutput(cmd)
561     cmd = 'cp -R %s/release/bin/%s/locale %s/%s.app/Contents/MacOS/%s/'%(bldroot,VERSION,installdir,binary,VERSION)
562     commands.getoutput(cmd)
563     cmd = 'cp %s/release/bin/%s/.Blanguages %s/%s.app/Contents/Resources/'%(bldroot,VERSION,installdir,binary)
564     commands.getoutput(cmd)
565     cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/python/'%(installdir,binary, VERSION)
566     commands.getoutput(cmd)
567     cmd = 'unzip -q %s/release/%s -d %s/%s.app/Contents/MacOS/%s/python/'%(libdir,python_zip,installdir,binary,VERSION)
568     commands.getoutput(cmd)
569
570     if binary == 'blender':#not copy everything for blenderplayer
571         cmd = 'cp -R %s/release/scripts %s/%s.app/Contents/MacOS/%s/'%(bldroot,installdir,binary,VERSION)
572         commands.getoutput(cmd)
573         cmd = 'cp -R %s/release/ui %s/%s.app/Contents/MacOS/%s/'%(bldroot,installdir,binary,VERSION)
574         commands.getoutput(cmd)
575         cmd = 'cp -R %s/release/io %s/%s.app/Contents/MacOS/%s/'%(bldroot,installdir,binary,VERSION)
576         commands.getoutput(cmd)
577
578     cmd = 'chmod +x  %s/%s.app/Contents/MacOS/%s'%(installdir,binary, binary)
579     commands.getoutput(cmd)
580     cmd = 'find %s/%s.app -name .svn -prune -exec rm -rf {} \;'%(installdir, binary)
581     commands.getoutput(cmd)
582     cmd = 'find %s/%s.app -name .DS_Store -exec rm -rf {} \;'%(installdir, binary)
583     commands.getoutput(cmd)
584     cmd = 'find %s/%s.app -name __MACOSX -exec rm -rf {} \;'%(installdir, binary)
585     commands.getoutput(cmd)
586
587 # extract copy system python, be sure to update other build systems
588 # when making changes to the files that are copied.
589 def my_unixpybundle_print(target, source, env):
590     pass
591
592 def UnixPyBundle(target=None, source=None, env=None):
593     # Any Unix except osx
594     #-- VERSION/python/lib/python3.1
595     
596     import commands
597     
598     def run(cmd):
599         print 'Install command:', cmd
600         commands.getoutput(cmd)
601
602     dir = os.path.join(env['BF_INSTALLDIR'], VERSION)
603
604     py_src =    env.subst( env['BF_PYTHON_LIBPATH'] + '/python'+env['BF_PYTHON_VERSION'] )
605     py_target =    env.subst( dir + '/python/lib/python'+env['BF_PYTHON_VERSION'] )
606     
607     # This is a bit weak, but dont install if its been installed before, makes rebuilds quite slow.
608     if os.path.exists(py_target):
609         print 'Using existing python from:'
610         print '\t"%s"' %            py_target
611         print '\t(skipping copy)\n'
612         return
613
614     # Copied from source/creator/CMakeLists.txt, keep in sync.
615     print 'Install python from:'
616     print '\t"%s" into...' % py_src
617     print '\t"%s"\n' % py_target
618
619     run("rm -rf '%s'" % py_target)
620     try:
621         os.makedirs(os.path.dirname(py_target)) # the final part is copied
622     except:
623         pass
624
625     run("cp -R '%s' '%s'" % (py_src, os.path.dirname(py_target)))
626     run("rm -rf '%s/distutils'" % py_target)
627     run("rm -rf '%s/lib2to3'" % py_target)
628     run("rm -rf '%s/config'" % py_target)
629     run("rm -rf '%s/config-*'" % py_target)
630     run("rm -rf '%s/site-packages'" % py_target)
631     run("mkdir '%s/site-packages'" % py_target)    # python needs it.'
632     run("rm -rf '%s/idlelib'" % py_target)
633     run("rm -rf '%s/tkinter'" % py_target)
634     run("rm -rf '%s/turtledemo'" % py_target)
635     run("rm -r '%s/turtle.py'" % py_target)
636     run("rm -f '%s/lib-dynload/_tkinter.so'" % py_target)
637
638     run("find '%s' -type d -name 'test' -prune -exec rm -rf {} ';'" % py_target)
639     run("find '%s' -type d -name '__pycache__' -exec rm -rf {} ';'" % py_target)
640     run("find '%s' -name '*.py[co]' -exec rm -rf {} ';'" % py_target)
641     run("find '%s' -name '*.so' -exec strip -s {} ';'" % py_target)
642     
643
644 #### END ACTION STUFF #########
645
646 def bsc(env, target, source):
647     
648     bd = os.path.dirname(target[0].abspath)
649     bscfile = '\"'+target[0].abspath+'\"'
650     bscpathcollect = '\"'+bd + os.sep + '*.sbr\"'
651     bscpathtmp = '\"'+bd + os.sep + 'bscmake.tmp\"'
652
653     os.system('dir /b/s '+bscpathcollect+' >'+bscpathtmp)
654
655     myfile = open(bscpathtmp[1:-1], 'r')
656     lines = myfile.readlines()
657     myfile.close()
658
659     newfile = open(bscpathtmp[1:-1], 'w')
660     for l in lines:
661         newfile.write('\"'+l[:-1]+'\"\n')
662     newfile.close()
663                 
664     os.system('bscmake /nologo /n /o'+bscfile+' @'+bscpathtmp)
665     os.system('del '+bscpathtmp)
666
667 class BlenderEnvironment(SConsEnvironment):
668
669     PyBundleActionAdded = False
670
671     def BlenderRes(self=None, libname=None, source=None, libtype=['core'], priority=[100]):
672         global libs
673         if not self or not libname or not source:
674             print bc.FAIL+'Cannot continue.  Missing argument for BlenderRes '+libname+bc.ENDC
675             self.Exit()
676         if self['OURPLATFORM'] not in ('win32-vc','win32-mingw','linuxcross', 'win64-vc'):
677             print bc.FAIL+'BlenderRes is for windows only!'+bc.END
678             self.Exit()
679         
680         print bc.HEADER+'Configuring resource '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC
681         lenv = self.Clone()
682         if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
683             res = lenv.RES('#'+root_build_dir+'lib/'+libname, source)
684         else:
685             res = lenv.RES(root_build_dir+'lib/'+libname, source)
686
687         
688         SConsEnvironment.Default(self, res)
689         resources.append(res)
690
691     def BlenderLib(self=None, libname=None, sources=None, includes=[], defines=[], libtype='common', priority = 100, compileflags=None, cc_compileflags=None, cxx_compileflags=None):
692         global vcp
693         if not self or not libname or not sources:
694             print bc.FAIL+'Cannot continue. Missing argument for BuildBlenderLib '+libname+bc.ENDC
695             self.Exit()
696
697         def list_substring(quickie, libname):
698             for q in quickie:
699                 if libname.find(q) != -1:
700                     return True
701             return False
702
703         if list_substring(quickie, libname) or len(quickie)==0:
704             if list_substring(quickdebug, libname):
705                 print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname +bc.ENDC+bc.OKBLUE+ " (debug mode)" + bc.ENDC
706             else:
707                 print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname + bc.ENDC
708             lenv = self.Clone()
709             lenv.Append(CPPPATH=includes)
710             lenv.Append(CPPDEFINES=defines)
711             if lenv['BF_DEBUG'] or (libname in quickdebug):
712                     lenv.Append(CFLAGS = lenv['BF_DEBUG_CFLAGS'])
713                     lenv.Append(CCFLAGS = lenv['BF_DEBUG_CCFLAGS'])
714                     lenv.Append(CXXFLAGS = lenv['BF_DEBUG_CXXFLAGS'])
715             else:
716                     lenv.Append(CFLAGS = lenv['REL_CFLAGS'])
717                     lenv.Append(CCFLAGS = lenv['REL_CCFLAGS'])
718                     lenv.Append(CXXFLAGS = lenv['REL_CXXFLAGS'])
719             if lenv['BF_PROFILE']:
720                     lenv.Append(CFLAGS = lenv['BF_PROFILE_CFLAGS'])
721                     lenv.Append(CCFLAGS = lenv['BF_PROFILE_CCFLAGS'])
722                     lenv.Append(CXXFLAGS = lenv['BF_PROFILE_CXXFLAGS'])
723             if compileflags:
724                 lenv.Replace(CFLAGS = compileflags)
725             if cc_compileflags:
726                 lenv.Replace(CCFLAGS = cc_compileflags)
727             if cxx_compileflags:
728                 lenv.Replace(CXXFLAGS = cxx_compileflags)
729             lenv.Append(CFLAGS = lenv['C_WARN'])
730             lenv.Append(CCFLAGS = lenv['CC_WARN'])
731             lenv.Append(CXXFLAGS = lenv['CXX_WARN'])
732
733             if lenv['OURPLATFORM'] == 'win64-vc':
734                 lenv.Append(LINKFLAGS = ['/MACHINE:X64'])
735
736             if lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
737                 if lenv['BF_DEBUG']:
738                     lenv.Append(CCFLAGS = ['/MTd'])
739                 else:
740                     lenv.Append(CCFLAGS = ['/MT'])
741             
742             targetdir = root_build_dir+'lib/' + libname
743             if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
744                 targetdir = '#'+targetdir
745             lib = lenv.Library(target= targetdir, source=sources)
746             SConsEnvironment.Default(self, lib) # we add to default target, because this way we get some kind of progress info during build
747             if self['BF_MSVS'] and self['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
748                 #if targetdir[0] == '#':
749                 #    targetdir = targetdir[1:-1]
750                 print "! ",targetdir+ '.vcproj' # + self['MSVSPROJECTSUFFIX']
751                 vcproject = self.MSVSProject(target = targetdir + '.vcproj', # + self['MSVSPROJECTSUFFIX'],
752                          srcs = sources,
753                          buildtarget = lib,
754                          variant = 'Release',
755                          auto_build_solution=0)
756                 vcp.append(vcproject)
757                 SConsEnvironment.Default(self, vcproject)
758         else:
759             print bc.WARNING+'Not building '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC+' for '+bc.OKBLUE+'BF_QUICK'+bc.ENDC
760         # note: libs is a global
761         add_lib_to_dict(self, libs, libtype, libname, priority)
762
763     def BlenderProg(self=None, builddir=None, progname=None, sources=None, libs=None, libpath=None, binarykind=''):
764         global vcp
765         print bc.HEADER+'Configuring program '+bc.ENDC+bc.OKGREEN+progname+bc.ENDC
766         lenv = self.Clone()
767         lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
768         if lenv['OURPLATFORM'] in ('win32-vc', 'cygwin', 'win64-vc'):
769             if lenv['BF_DEBUG']:
770                 lenv.Prepend(LINKFLAGS = ['/DEBUG','/PDB:'+progname+'.pdb','/NODEFAULTLIB:libcmt'])
771         if  lenv['OURPLATFORM']=='linux2':
772             if lenv['WITH_BF_PYTHON']:
773                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
774         if  lenv['OURPLATFORM']=='sunos5':
775             if lenv['WITH_BF_PYTHON']:
776                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
777             if lenv['CXX'].endswith('CC'):
778                  lenv.Replace(LINK = '$CXX')
779         if  lenv['OURPLATFORM']=='darwin':
780             if lenv['WITH_BF_PYTHON']:
781                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
782             lenv.Append(LINKFLAGS = lenv['BF_OPENGL_LINKFLAGS'])
783         if lenv['BF_PROFILE']:
784             lenv.Append(LINKFLAGS = lenv['BF_PROFILE_LINKFLAGS'])
785         if root_build_dir[0]==os.sep or root_build_dir[1]==':':
786             lenv.Append(LIBPATH=root_build_dir + '/lib')
787         lenv.Append(LIBPATH=libpath)
788         lenv.Append(LIBS=libs)
789         if lenv['WITH_BF_QUICKTIME']:
790              lenv.Append(LIBS = lenv['BF_QUICKTIME_LIB'])
791              lenv.Append(LIBPATH = lenv['BF_QUICKTIME_LIBPATH'])
792         prog = lenv.Program(target=builddir+'bin/'+progname, source=sources)
793         if lenv['BF_DEBUG'] and lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc') and lenv['BF_BSC']:
794             f = lenv.File(progname + '.bsc', builddir)
795             brs = lenv.Command(f, prog, [bsc])
796             SConsEnvironment.Default(self, brs)
797         SConsEnvironment.Default(self, prog)
798         if self['BF_MSVS'] and self['OURPLATFORM'] in ('win32-vc', 'win64-vc') and progname == 'blender':
799             print "! ",builddir + "/" + progname + '.sln'
800             sln = self.MSVSProject(target = builddir + "/" + progname + '.sln',
801                      projects= vcp,
802                      variant = 'Release')
803             SConsEnvironment.Default(self, sln)
804         program_list.append(prog)
805         if  lenv['OURPLATFORM']=='darwin':
806             lenv['BINARYKIND'] = binarykind
807             lenv.AddPostAction(prog,Action(AppIt,strfunction=my_appit_print))
808         elif os.sep == '/' and lenv['OURPLATFORM'] != 'linuxcross': # any unix (except cross-compilation)
809             if lenv['WITH_BF_PYTHON']:
810                 if not lenv['WITHOUT_BF_INSTALL'] and not lenv['WITHOUT_BF_PYTHON_INSTALL'] and not BlenderEnvironment.PyBundleActionAdded:
811                     lenv.AddPostAction(prog,Action(UnixPyBundle,strfunction=my_unixpybundle_print))
812                     BlenderEnvironment.PyBundleActionAdded = True
813         elif lenv['OURPLATFORM'].startswith('win') or lenv['OURPLATFORM'] == 'linuxcross': # windows or cross-compilation
814             if lenv['WITH_BF_PYTHON']:
815                 if not lenv['WITHOUT_BF_PYTHON_INSTALL'] and not BlenderEnvironment.PyBundleActionAdded:
816                     lenv.AddPostAction(prog,Action(WinPyBundle,strfunction=my_winpybundle_print))
817                     BlenderEnvironment.PyBundleActionAdded = True
818         return prog
819
820     def Glob(lenv, pattern):
821         path = string.replace(GetBuildPath(lenv,'SConscript'),'SConscript', '')
822         files = []
823         for i in glob.glob(path + pattern):
824             files.append(string.replace(i, path, ''))
825         return files