OSX: commit the omp_set_simulation_threads applescript and copy-routines
[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_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_TIFF']:
151         libincs += Split(lenv['BF_TIFF_LIBPATH'])
152         if lenv['WITH_BF_STATICTIFF']:
153             statlibs += Split(lenv['BF_TIFF_LIB_STATIC'])
154     if lenv['WITH_BF_ZLIB'] and lenv['WITH_BF_STATICZLIB']:
155         statlibs += Split(lenv['BF_ZLIB_LIB_STATIC'])
156     if lenv['WITH_BF_FFTW3']:
157         libincs += Split(lenv['BF_FFTW3_LIBPATH'])
158         if lenv['WITH_BF_STATICFFTW3']:
159             statlibs += Split(lenv['BF_FFTW3_LIB_STATIC'])
160     if lenv['WITH_BF_FFMPEG'] and lenv['WITH_BF_STATICFFMPEG']:
161         statlibs += Split(lenv['BF_FFMPEG_LIB_STATIC'])
162     if lenv['WITH_BF_INTERNATIONAL']:
163         libincs += Split(lenv['BF_GETTEXT_LIBPATH'])
164         if lenv['WITH_BF_GETTEXT_STATIC']:
165             statlibs += Split(lenv['BF_GETTEXT_LIB_STATIC'])
166         if lenv['WITH_BF_FREETYPE_STATIC']:
167             statlibs += Split(lenv['BF_FREETYPE_LIB_STATIC'])
168     if lenv['WITH_BF_OPENAL']:
169         libincs += Split(lenv['BF_OPENAL_LIBPATH'])
170         if lenv['WITH_BF_STATICOPENAL']:
171             statlibs += Split(lenv['BF_OPENAL_LIB_STATIC'])
172     if lenv['WITH_BF_STATICOPENGL']:
173         statlibs += Split(lenv['BF_OPENGL_LIB_STATIC'])
174     if lenv['WITH_BF_STATICCXX']:
175         statlibs += Split(lenv['BF_CXX_LIB_STATIC'])
176
177     if lenv['WITH_BF_PYTHON'] and lenv['WITH_BF_STATICPYTHON']:
178         statlibs += Split(lenv['BF_PYTHON_LIB_STATIC'])
179
180     if lenv['WITH_BF_SNDFILE'] and lenv['WITH_BF_STATICSNDFILE']:
181         statlibs += Split(lenv['BF_SNDFILE_LIB_STATIC'])
182
183     if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
184         libincs += Split(lenv['BF_PTHREADS_LIBPATH'])
185
186     if lenv['WITH_BF_COLLADA']:
187         libincs += Split(lenv['BF_OPENCOLLADA_LIBPATH'])
188         if lenv['OURPLATFORM'] not in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
189             libincs += Split(lenv['BF_PCRE_LIBPATH'])
190             libincs += Split(lenv['BF_EXPAT_LIBPATH'])
191
192     if lenv['WITH_BF_OPENMP']:
193         if lenv['OURPLATFORM'] == 'linuxcross':
194             libincs += Split(lenv['BF_OPENMP_LIBPATH'])
195
196     # setting this last so any overriding of manually libs could be handled
197     if lenv['OURPLATFORM'] not in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'):
198         libincs.append('/usr/lib')
199
200     if lenv['WITH_BF_JEMALLOC']:
201         libincs += Split(lenv['BF_JEMALLOC_LIBPATH'])
202         if lenv['WITH_BF_STATICJEMALLOC']:
203             statlibs += Split(lenv['BF_JEMALLOC_LIB_STATIC'])
204
205     if lenv['OURPLATFORM']=='linux':
206         if lenv['WITH_BF_3DMOUSE']:
207             libincs += Split(lenv['BF_3DMOUSE_LIBPATH'])
208             if lenv['WITH_BF_STATIC3DMOUSE']:
209                 statlibs += Split(lenv['BF_3DMOUSE_LIB_STATIC'])
210
211     return statlibs, libincs
212
213 def setup_syslibs(lenv):
214     syslibs = [
215         
216         lenv['BF_JPEG_LIB'],
217         lenv['BF_PNG_LIB'],
218         ]
219
220     if not lenv['WITH_BF_FREETYPE_STATIC']:
221         syslibs += Split(lenv['BF_FREETYPE_LIB'])
222     if lenv['WITH_BF_PYTHON'] and not lenv['WITH_BF_STATICPYTHON']:
223         if lenv['BF_DEBUG'] and lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc', 'win32-mingw'):
224             syslibs.append(lenv['BF_PYTHON_LIB']+'_d')
225         else:
226             syslibs.append(lenv['BF_PYTHON_LIB'])
227     if lenv['WITH_BF_INTERNATIONAL'] and not lenv['WITH_BF_GETTEXT_STATIC']:
228         syslibs += Split(lenv['BF_GETTEXT_LIB'])
229     if lenv['WITH_BF_OPENAL']:
230         if not lenv['WITH_BF_STATICOPENAL']:
231             syslibs += Split(lenv['BF_OPENAL_LIB'])
232     if lenv['WITH_BF_OPENMP'] and lenv['CC'] != 'icc':
233         if lenv['CC'] == 'cl.exe':
234             syslibs += ['vcomp']
235         else:
236             syslibs += ['gomp']
237     if lenv['WITH_BF_ICONV']:
238         syslibs += Split(lenv['BF_ICONV_LIB'])
239     if lenv['WITH_BF_OPENEXR'] and not lenv['WITH_BF_STATICOPENEXR']:
240         syslibs += Split(lenv['BF_OPENEXR_LIB'])
241     if lenv['WITH_BF_TIFF'] and not lenv['WITH_BF_STATICTIFF']:
242         syslibs += Split(lenv['BF_TIFF_LIB'])
243     if lenv['WITH_BF_ZLIB'] and not lenv['WITH_BF_STATICZLIB']:
244         syslibs += Split(lenv['BF_ZLIB_LIB'])
245     if lenv['WITH_BF_FFMPEG'] and not lenv['WITH_BF_STATICFFMPEG']:
246         syslibs += Split(lenv['BF_FFMPEG_LIB'])
247         if lenv['WITH_BF_OGG']:
248             syslibs += Split(lenv['BF_OGG_LIB'])
249     if lenv['WITH_BF_JACK']:
250             syslibs += Split(lenv['BF_JACK_LIB'])
251     if lenv['WITH_BF_SNDFILE'] and not lenv['WITH_BF_STATICSNDFILE']:
252             syslibs += Split(lenv['BF_SNDFILE_LIB'])
253     if lenv['WITH_BF_FFTW3'] and not lenv['WITH_BF_STATICFFTW3']:
254         syslibs += Split(lenv['BF_FFTW3_LIB'])
255     if lenv['WITH_BF_SDL']:
256         syslibs += Split(lenv['BF_SDL_LIB'])
257     if not lenv['WITH_BF_STATICOPENGL']:
258         syslibs += Split(lenv['BF_OPENGL_LIB'])
259     if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw','linuxcross', 'win64-vc'):
260         syslibs += Split(lenv['BF_PTHREADS_LIB'])
261     if lenv['WITH_BF_COLLADA']:
262         syslibs.append(lenv['BF_PCRE_LIB'])
263         if lenv['BF_DEBUG']:
264             syslibs += [colladalib+'_d' for colladalib in Split(lenv['BF_OPENCOLLADA_LIB'])]
265         else:
266             syslibs += Split(lenv['BF_OPENCOLLADA_LIB'])
267         syslibs.append(lenv['BF_EXPAT_LIB'])
268
269     if lenv['WITH_BF_JEMALLOC']:
270         if not lenv['WITH_BF_STATICJEMALLOC']:
271             syslibs += Split(lenv['BF_JEMALLOC_LIB'])
272
273     if lenv['OURPLATFORM']=='linux':
274         if lenv['WITH_BF_3DMOUSE']:
275             if not lenv['WITH_BF_STATIC3DMOUSE']:
276                 syslibs += Split(lenv['BF_3DMOUSE_LIB'])
277
278     syslibs += lenv['LLIBS']
279
280     return syslibs
281
282 def propose_priorities():
283     print bc.OKBLUE+"Priorities:"+bc.ENDC
284     for t in possible_types:
285         print bc.OKGREEN+"\t"+t+bc.ENDC
286         new_priority = 0
287         curlib = libs[t]
288         sortlist = curlib.keys()
289         sortlist.sort()
290
291         for sk in sortlist:
292             v = curlib[sk]
293             #for p,v in sorted(libs[t].iteritems()):
294             print "\t\t",new_priority, v
295             new_priority += 5
296
297 # emits the necessary file objects for creator.c, to be used in creating
298 # the final blender executable
299 def creator(env):
300     sources = ['creator.c']# + Blender.buildinfo(env, "dynamic") + Blender.resources
301
302     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']]
303
304     defs = []
305     if env['WITH_BF_QUICKTIME']:
306         incs.append(env['BF_QUICKTIME_INC'])
307         defs.append('WITH_QUICKTIME')
308
309     if env['WITH_BF_BINRELOC']:
310         incs.append('#/extern/binreloc/include')
311         defs.append('WITH_BINRELOC')
312
313     if env['WITH_BF_OPENEXR']:
314         defs.append('WITH_OPENEXR')
315
316     if env['WITH_BF_TIFF']:
317         defs.append('WITH_TIFF')
318
319     if not env['WITH_BF_SDL']:
320         defs.append('DISABLE_SDL')
321
322     if env['WITH_BF_PYTHON']:
323         incs.append('#/source/blender/python')
324         defs.append('WITH_PYTHON')
325         if env['BF_DEBUG']:
326             defs.append('_DEBUG')
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                                     'WITH_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     if env['WITH_OSX_STATICPYTHON']:
533         print("unzipping to app-bundle: %s"%(python_zip))
534     else:
535         print("dynamic build - make sure to have python3.x-framework installed")
536     bldroot = env.Dir('.').abspath
537     binary = env['BINARYKIND']
538      
539     if b=='verse':
540         print bc.OKBLUE+"no bundle for verse"+bc.ENDC 
541         return 0
542     
543     sourcedir = bldroot + '/source/darwin/%s.app'%binary
544     sourceinfo = bldroot + "/source/darwin/%s.app/Contents/Info.plist"%binary
545     targetinfo = installdir +'/' + "%s.app/Contents/Info.plist"%binary
546     cmd = installdir + '/' +'%s.app'%binary
547     
548     if os.path.isdir(cmd):
549         shutil.rmtree(cmd)
550     shutil.copytree(sourcedir, cmd)
551     cmd = "cat %s | sed s/\$\{MACOSX_BUNDLE_SHORT_VERSION_STRING\}/%s/ | "%(sourceinfo,VERSION)
552     cmd += "sed s/\$\{MACOSX_BUNDLE_LONG_VERSION_STRING\}/%s,\ %s/g > %s"%(VERSION,time.strftime("%Y-%b-%d"),targetinfo)
553     commands.getoutput(cmd)
554     cmd = 'cp %s/%s %s/%s.app/Contents/MacOS/%s'%(builddir, binary,installdir, binary, binary)
555     commands.getoutput(cmd)
556     cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/'%(installdir, binary, VERSION)
557     commands.getoutput(cmd)
558     cmd = installdir + '/%s.app/Contents/MacOS/%s'%(binary,VERSION)
559
560     # blenderplayer doesn't need all the files
561     if binary == 'blender':
562         cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/datafiles'%(installdir, binary, VERSION)
563         commands.getoutput(cmd)
564         cmd = 'cp -R %s/release/bin/.blender/locale %s/%s.app/Contents/MacOS/%s/datafiles/'%(bldroot,installdir,binary,VERSION)
565         commands.getoutput(cmd)
566         cmd = 'cp -R %s/release/bin/.blender/fonts %s/%s.app/Contents/MacOS/%s/datafiles/'%(bldroot,installdir,binary,VERSION)
567         commands.getoutput(cmd)
568         cmd = 'cp -R %s/release/scripts %s/%s.app/Contents/MacOS/%s/'%(bldroot,installdir,binary,VERSION)
569         commands.getoutput(cmd)
570
571     if env['WITH_OSX_STATICPYTHON']:
572         cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/python/'%(installdir,binary, VERSION)
573         commands.getoutput(cmd)
574         cmd = 'unzip -q %s/release/%s -d %s/%s.app/Contents/MacOS/%s/python/'%(libdir,python_zip,installdir,binary,VERSION)
575         commands.getoutput(cmd)
576
577     cmd = 'chmod +x  %s/%s.app/Contents/MacOS/%s'%(installdir,binary, binary)
578     commands.getoutput(cmd)
579     cmd = 'find %s/%s.app -name .svn -prune -exec rm -rf {} \;'%(installdir, binary)
580     commands.getoutput(cmd)
581     cmd = 'find %s/%s.app -name .DS_Store -exec rm -rf {} \;'%(installdir, binary)
582     commands.getoutput(cmd)
583     cmd = 'find %s/%s.app -name __MACOSX -exec rm -rf {} \;'%(installdir, binary)
584     commands.getoutput(cmd)
585     if env['CC'].endswith('4.6.1'): # for correct errorhandling with gcc 4.6.1 we need the gcc.dylib to link, thus distribute in app-bundle
586         cmd = 'mkdir %s/%s.app/Contents/MacOS/lib'%(installdir, binary)
587         commands.getoutput(cmd)
588         instname = env['BF_CXX']
589         cmd = 'cp %s/lib/libgcc_s.1.dylib %s/%s.app/Contents/MacOS/lib/'%(instname, installdir, binary)
590         commands.getoutput(cmd)
591         cmd = 'install_name_tool -id @executable_path/lib/libgcc_s.1.dylib %s/%s.app/Contents/MacOS/lib/libgcc_s.1.dylib'%(installdir, binary)
592         commands.getoutput(cmd)
593         cmd = 'install_name_tool -change %s/lib/libgcc_s.1.dylib  @executable_path/lib/libgcc_s.1.dylib %s/%s.app/Contents/MacOS/%s'%(instname, installdir, binary, binary)
594         commands.getoutput(cmd)
595         cmd = 'cp -R %s/source/darwin/set_simulation_threads.app %s/'%(bldroot, installdir) # the omp_num_threads applescript
596         commands.getoutput(cmd)
597
598 # extract copy system python, be sure to update other build systems
599 # when making changes to the files that are copied.
600 def my_unixpybundle_print(target, source, env):
601     pass
602
603 def UnixPyBundle(target=None, source=None, env=None):
604     # Any Unix except osx
605     #-- VERSION/python/lib/python3.1
606     
607     import commands
608     
609     def run(cmd):
610         print 'Install command:', cmd
611         commands.getoutput(cmd)
612
613     dir = os.path.join(env['BF_INSTALLDIR'], VERSION)
614
615     py_src =    env.subst( env['BF_PYTHON_LIBPATH'] + '/python'+env['BF_PYTHON_VERSION'] )
616     py_target =    env.subst( dir + '/python/lib/python'+env['BF_PYTHON_VERSION'] )
617     
618     # This is a bit weak, but dont install if its been installed before, makes rebuilds quite slow.
619     if os.path.exists(py_target):
620         print 'Using existing python from:'
621         print '\t"%s"' %            py_target
622         print '\t(skipping copy)\n'
623         return
624
625     # Copied from source/creator/CMakeLists.txt, keep in sync.
626     print 'Install python from:'
627     print '\t"%s" into...' % py_src
628     print '\t"%s"\n' % py_target
629
630     run("rm -rf '%s'" % py_target)
631     try:
632         os.makedirs(os.path.dirname(py_target)) # the final part is copied
633     except:
634         pass
635
636     run("cp -R '%s' '%s'" % (py_src, os.path.dirname(py_target)))
637     run("rm -rf '%s/distutils'" % py_target)
638     run("rm -rf '%s/lib2to3'" % py_target)
639     run("rm -rf '%s/config'" % py_target)
640
641     for f in os.listdir(py_target):
642         if f.startswith("config-"):
643             run("rm -rf '%s/%s'" % (py_target, f))
644
645     run("rm -rf '%s/site-packages'" % py_target)
646     run("mkdir '%s/site-packages'" % py_target)    # python needs it.'
647     run("rm -rf '%s/idlelib'" % py_target)
648     run("rm -rf '%s/tkinter'" % py_target)
649     run("rm -rf '%s/turtledemo'" % py_target)
650     run("rm -r '%s/turtle.py'" % py_target)
651     run("rm -f '%s/lib-dynload/_tkinter.so'" % py_target)
652
653     run("find '%s' -type d -name 'test' -prune -exec rm -rf {} ';'" % py_target)
654     run("find '%s' -type d -name '__pycache__' -exec rm -rf {} ';'" % py_target)
655     run("find '%s' -name '*.py[co]' -exec rm -rf {} ';'" % py_target)
656     run("find '%s' -name '*.so' -exec strip -s {} ';'" % py_target)
657     
658
659 #### END ACTION STUFF #########
660
661 def bsc(env, target, source):
662     
663     bd = os.path.dirname(target[0].abspath)
664     bscfile = '\"'+target[0].abspath+'\"'
665     bscpathcollect = '\"'+bd + os.sep + '*.sbr\"'
666     bscpathtmp = '\"'+bd + os.sep + 'bscmake.tmp\"'
667
668     os.system('dir /b/s '+bscpathcollect+' >'+bscpathtmp)
669
670     myfile = open(bscpathtmp[1:-1], 'r')
671     lines = myfile.readlines()
672     myfile.close()
673
674     newfile = open(bscpathtmp[1:-1], 'w')
675     for l in lines:
676         newfile.write('\"'+l[:-1]+'\"\n')
677     newfile.close()
678                 
679     os.system('bscmake /nologo /n /o'+bscfile+' @'+bscpathtmp)
680     os.system('del '+bscpathtmp)
681
682 class BlenderEnvironment(SConsEnvironment):
683
684     PyBundleActionAdded = False
685
686     def BlenderRes(self=None, libname=None, source=None, libtype=['core'], priority=[100]):
687         global libs
688         if not self or not libname or not source:
689             print bc.FAIL+'Cannot continue.  Missing argument for BlenderRes '+libname+bc.ENDC
690             self.Exit()
691         if self['OURPLATFORM'] not in ('win32-vc','win32-mingw','linuxcross', 'win64-vc'):
692             print bc.FAIL+'BlenderRes is for windows only!'+bc.END
693             self.Exit()
694         
695         print bc.HEADER+'Configuring resource '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC
696         lenv = self.Clone()
697         if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
698             res = lenv.RES('#'+root_build_dir+'lib/'+libname, source)
699         else:
700             res = lenv.RES(root_build_dir+'lib/'+libname, source)
701
702         
703         SConsEnvironment.Default(self, res)
704         resources.append(res)
705
706     def BlenderLib(self=None, libname=None, sources=None, includes=[], defines=[], libtype='common', priority = 100, compileflags=None, cc_compileflags=None, cxx_compileflags=None, cc_compilerchange=None, cxx_compilerchange=None):
707         global vcp
708         if not self or not libname or not sources:
709             print bc.FAIL+'Cannot continue. Missing argument for BuildBlenderLib '+libname+bc.ENDC
710             self.Exit()
711
712         def list_substring(quickie, libname):
713             for q in quickie:
714                 if libname.find(q) != -1:
715                     return True
716             return False
717
718         if list_substring(quickie, libname) or len(quickie)==0:
719             if list_substring(quickdebug, libname):
720                 print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname +bc.ENDC+bc.OKBLUE+ " (debug mode)" + bc.ENDC
721             else:
722                 print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname + bc.ENDC
723             lenv = self.Clone()
724             lenv.Append(CPPPATH=includes)
725             lenv.Append(CPPDEFINES=defines)
726             if lenv['BF_DEBUG'] or (libname in quickdebug):
727                     lenv.Append(CFLAGS = lenv['BF_DEBUG_CFLAGS'])
728                     lenv.Append(CCFLAGS = lenv['BF_DEBUG_CCFLAGS'])
729                     lenv.Append(CXXFLAGS = lenv['BF_DEBUG_CXXFLAGS'])
730             else:
731                     lenv.Append(CFLAGS = lenv['REL_CFLAGS'])
732                     lenv.Append(CCFLAGS = lenv['REL_CCFLAGS'])
733                     lenv.Append(CXXFLAGS = lenv['REL_CXXFLAGS'])
734             if lenv['BF_PROFILE']:
735                     lenv.Append(CFLAGS = lenv['BF_PROFILE_CFLAGS'])
736                     lenv.Append(CCFLAGS = lenv['BF_PROFILE_CCFLAGS'])
737                     lenv.Append(CXXFLAGS = lenv['BF_PROFILE_CXXFLAGS'])
738             if compileflags:
739                 lenv.Replace(CFLAGS = compileflags)
740             if cc_compileflags:
741                 lenv.Replace(CCFLAGS = cc_compileflags)
742             if cxx_compileflags:
743                 lenv.Replace(CXXFLAGS = cxx_compileflags)
744             if cc_compilerchange:
745                 lenv.Replace(CC = cc_compilerchange)
746             if cxx_compilerchange:
747                 lenv.Replace(CXX = cxx_compilerchange)
748             lenv.Append(CFLAGS = lenv['C_WARN'])
749             lenv.Append(CCFLAGS = lenv['CC_WARN'])
750             lenv.Append(CXXFLAGS = lenv['CXX_WARN'])
751
752             if lenv['OURPLATFORM'] == 'win64-vc':
753                 lenv.Append(LINKFLAGS = ['/MACHINE:X64'])
754
755             if lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
756                 if lenv['BF_DEBUG']:
757                     lenv.Append(CCFLAGS = ['/MTd'])
758                 else:
759                     lenv.Append(CCFLAGS = ['/MT'])
760             
761             targetdir = root_build_dir+'lib/' + libname
762             if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
763                 targetdir = '#'+targetdir
764             lib = lenv.Library(target= targetdir, source=sources)
765             SConsEnvironment.Default(self, lib) # we add to default target, because this way we get some kind of progress info during build
766             if self['BF_MSVS'] and self['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
767                 #if targetdir[0] == '#':
768                 #    targetdir = targetdir[1:-1]
769                 print "! ",targetdir+ '.vcproj' # + self['MSVSPROJECTSUFFIX']
770                 vcproject = self.MSVSProject(target = targetdir + '.vcproj', # + self['MSVSPROJECTSUFFIX'],
771                          srcs = sources,
772                          buildtarget = lib,
773                          variant = 'Release',
774                          auto_build_solution=0)
775                 vcp.append(vcproject)
776                 SConsEnvironment.Default(self, vcproject)
777         else:
778             print bc.WARNING+'Not building '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC+' for '+bc.OKBLUE+'BF_QUICK'+bc.ENDC
779         # note: libs is a global
780         add_lib_to_dict(self, libs, libtype, libname, priority)
781
782     def BlenderProg(self=None, builddir=None, progname=None, sources=None, libs=None, libpath=None, binarykind=''):
783         global vcp
784         print bc.HEADER+'Configuring program '+bc.ENDC+bc.OKGREEN+progname+bc.ENDC
785         lenv = self.Clone()
786         lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
787         if lenv['OURPLATFORM'] in ('win32-vc', 'cygwin', 'win64-vc'):
788             if lenv['BF_DEBUG']:
789                 lenv.Prepend(LINKFLAGS = ['/DEBUG','/PDB:'+progname+'.pdb','/NODEFAULTLIB:libcmt'])
790         if  lenv['OURPLATFORM']=='linux':
791             if lenv['WITH_BF_PYTHON']:
792                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
793         if  lenv['OURPLATFORM']=='sunos5':
794             if lenv['WITH_BF_PYTHON']:
795                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
796             if lenv['CXX'].endswith('CC'):
797                  lenv.Replace(LINK = '$CXX')
798         if  lenv['OURPLATFORM']=='darwin':
799             if lenv['WITH_BF_PYTHON']:
800                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
801             lenv.Append(LINKFLAGS = lenv['BF_OPENGL_LINKFLAGS'])
802         if lenv['BF_PROFILE']:
803             lenv.Append(LINKFLAGS = lenv['BF_PROFILE_LINKFLAGS'])
804         if root_build_dir[0]==os.sep or root_build_dir[1]==':':
805             lenv.Append(LIBPATH=root_build_dir + '/lib')
806         lenv.Append(LIBPATH=libpath)
807         lenv.Append(LIBS=libs)
808         if lenv['WITH_BF_QUICKTIME']:
809              lenv.Append(LIBS = lenv['BF_QUICKTIME_LIB'])
810              lenv.Append(LIBPATH = lenv['BF_QUICKTIME_LIBPATH'])
811         prog = lenv.Program(target=builddir+'bin/'+progname, source=sources)
812         if lenv['BF_DEBUG'] and lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc') and lenv['BF_BSC']:
813             f = lenv.File(progname + '.bsc', builddir)
814             brs = lenv.Command(f, prog, [bsc])
815             SConsEnvironment.Default(self, brs)
816         SConsEnvironment.Default(self, prog)
817         if self['BF_MSVS'] and self['OURPLATFORM'] in ('win32-vc', 'win64-vc') and progname == 'blender':
818             print "! ",builddir + "/" + progname + '.sln'
819             sln = self.MSVSProject(target = builddir + "/" + progname + '.sln',
820                      projects= vcp,
821                      variant = 'Release')
822             SConsEnvironment.Default(self, sln)
823         program_list.append(prog)
824         if  lenv['OURPLATFORM']=='darwin':
825             lenv['BINARYKIND'] = binarykind
826             lenv.AddPostAction(prog,Action(AppIt,strfunction=my_appit_print))
827         elif os.sep == '/' and lenv['OURPLATFORM'] != 'linuxcross': # any unix (except cross-compilation)
828             if lenv['WITH_BF_PYTHON']:
829                 if not lenv['WITHOUT_BF_INSTALL'] and not lenv['WITHOUT_BF_PYTHON_INSTALL'] and not BlenderEnvironment.PyBundleActionAdded:
830                     lenv.AddPostAction(prog,Action(UnixPyBundle,strfunction=my_unixpybundle_print))
831                     BlenderEnvironment.PyBundleActionAdded = True
832         elif lenv['OURPLATFORM'].startswith('win') or lenv['OURPLATFORM'] == 'linuxcross': # windows or cross-compilation
833             if lenv['WITH_BF_PYTHON']:
834                 if not lenv['WITHOUT_BF_PYTHON_INSTALL'] and not BlenderEnvironment.PyBundleActionAdded:
835                     lenv.AddPostAction(prog,Action(WinPyBundle,strfunction=my_winpybundle_print))
836                     BlenderEnvironment.PyBundleActionAdded = True
837         return prog
838
839     def Glob(lenv, pattern):
840         path = string.replace(GetBuildPath(lenv,'SConscript'),'SConscript', '')
841         files = []
842         for i in glob.glob(path + pattern):
843             files.append(string.replace(i, path, ''))
844         return files