Merging r38265 through r38295 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_LIBMV']:
319         incs.append('#/extern/libmv')
320         defs.append('WITH_LIBMV')
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['BF_BUILDINFO']:
329         defs.append('BUILD_DATE')
330         defs.append('NAN_BUILDINFO')
331         
332     if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
333         incs.append(env['BF_PTHREADS_INC'])
334
335     env.Append(CPPDEFINES=defs)
336     env.Append(CPPPATH=incs)
337     obj = [env.Object(root_build_dir+'source/creator/creator/creator', ['#source/creator/creator.c'])]
338
339     return obj
340
341 ## TODO: see if this can be made in an emitter
342 def buildinfo(lenv, build_type):
343     """
344     Generate a buildinfo object
345     """
346     build_date = time.strftime ("%Y-%m-%d")
347     build_time = time.strftime ("%H:%M:%S")
348     build_rev = os.popen('svnversion').read()[:-1] # remove \n
349     if build_rev == '': 
350         build_rev = '-UNKNOWN-'
351     if lenv['BF_DEBUG']:
352         build_type = "Debug"
353         build_cflags = ' '.join(lenv['CFLAGS'] + lenv['CCFLAGS'] + lenv['BF_DEBUG_CCFLAGS'] + lenv['CPPFLAGS'])
354         build_cxxflags = ' '.join(lenv['CCFLAGS'] + lenv['CXXFLAGS'] + lenv['CPPFLAGS'])
355     else:
356         build_type = "Release"
357         build_cflags = ' '.join(lenv['CFLAGS'] + lenv['CCFLAGS'] + lenv['REL_CFLAGS'] + lenv['REL_CCFLAGS'] + lenv['CPPFLAGS'])
358         build_cxxflags = ' '.join(lenv['CCFLAGS'] + lenv['CXXFLAGS'] + lenv['REL_CXXFLAGS'] + lenv['REL_CCFLAGS'] + lenv['CPPFLAGS'])
359
360     build_linkflags = ' '.join(lenv['PLATFORM_LINKFLAGS'])
361
362     obj = []
363     if lenv['BF_BUILDINFO']:
364         lenv.Append (CPPDEFINES = ['BUILD_TIME="%s"'%(build_time),
365                                     'BUILD_DATE="%s"'%(build_date),
366                                     'BUILD_TYPE="%s"'%(build_type),
367                                     'BUILD_REV="%s"'%(build_rev),
368                                     'NAN_BUILDINFO',
369                                     'BUILD_PLATFORM="%s:%s"'%(platform.system(), platform.architecture()[0]),
370                                     'BUILD_CFLAGS=\\"%s\\"'%(build_cflags),
371                                     'BUILD_CXXFLAGS=\\"%s\\"'%(build_cxxflags),
372                                     'BUILD_LINKFLAGS=\\"%s\\"'%(build_linkflags),
373                                     'BUILD_SYSTEM="SCons"'
374                     ])
375
376         lenv.Append (CPPPATH = [root_build_dir+'source/blender/blenkernel'])
377
378         obj = [lenv.Object (root_build_dir+'source/creator/%s_buildinfo'%build_type, ['#source/creator/buildinfo.c'])]
379
380     return obj
381
382 ##### END LIB STUFF ############
383
384 ##### ACTION STUFF #############
385
386 def my_print_cmd_line(self, s, target, source, env):
387     sys.stdout.write(' ' * 70 + '\r')
388     sys.stdout.flush()
389     sys.stdout.write(s + "\r")
390     sys.stdout.flush()
391
392 def my_compile_print(target, source, env):
393     a = '%s' % (source[0])
394     d, f = os.path.split(a)
395     return bc.OKBLUE+"Compiling"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
396
397 def my_moc_print(target, source, env):
398     a = '%s' % (source[0])
399     d, f = os.path.split(a)
400     return bc.OKBLUE+"Creating MOC"+bc.ENDC+ " ==> '"+bc.OKGREEN+"%s" %(f) + "'"+bc.ENDC
401
402 def my_linking_print(target, source, env):
403     t = '%s' % (target[0])
404     d, f = os.path.split(t)
405     return bc.OKBLUE+"Linking library"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
406
407 def my_program_print(target, source, env):
408     t = '%s' % (target[0])
409     d, f = os.path.split(t)
410     return bc.OKBLUE+"Linking program"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
411
412 def msvc_hack(env):
413     static_lib = SCons.Tool.createStaticLibBuilder(env)
414     program = SCons.Tool.createProgBuilder(env)
415     
416     env['BUILDERS']['Library'] = static_lib
417     env['BUILDERS']['StaticLibrary'] = static_lib
418     env['BUILDERS']['Program'] = program
419         
420 def set_quiet_output(env):
421     mycaction = Action("$CCCOM", strfunction=my_compile_print)
422     myshcaction = Action("$SHCCCOM", strfunction=my_compile_print)
423     mycppaction = Action("$CXXCOM", strfunction=my_compile_print)
424     myshcppaction = Action("$SHCXXCOM", strfunction=my_compile_print)
425     mylibaction = Action("$ARCOM", strfunction=my_linking_print)
426     mylinkaction = Action("$LINKCOM", strfunction=my_program_print)
427
428     static_ob, shared_ob = SCons.Tool.createObjBuilders(env)
429     static_ob.add_action('.c', mycaction)
430     static_ob.add_action('.cpp', mycppaction)
431     shared_ob.add_action('.c', myshcaction)
432     shared_ob.add_action('.cpp', myshcppaction)
433
434     static_lib = SCons.Builder.Builder(action = mylibaction,
435                                        emitter = '$LIBEMITTER',
436                                        prefix = '$LIBPREFIX',
437                                        suffix = '$LIBSUFFIX',
438                                        src_suffix = '$OBJSUFFIX',
439                                        src_builder = 'StaticObject')
440
441     program = SCons.Builder.Builder(action = mylinkaction,
442                                     emitter = '$PROGEMITTER',
443                                     prefix = '$PROGPREFIX',
444                                     suffix = '$PROGSUFFIX',
445                                     src_suffix = '$OBJSUFFIX',
446                                     src_builder = 'Object',
447                                     target_scanner = SCons.Defaults.ProgScan)
448
449     env['BUILDERS']['Object'] = static_ob
450     env['BUILDERS']['StaticObject'] = static_ob
451     env['BUILDERS']['StaticLibrary'] = static_lib
452     env['BUILDERS']['Library'] = static_lib
453     env['BUILDERS']['Program'] = program
454     if env['BF_LINE_OVERWRITE']:
455         SCons.Action._ActionAction.print_cmd_line = my_print_cmd_line
456
457 def untar_pybundle(from_tar,to_dir,exclude_re):
458     tar= tarfile.open(from_tar, mode='r')
459     exclude_re= list(exclude_re) #single re object or list of re objects
460     debug= 0 #list files instead of unpacking
461     good= []
462     if debug: print '\nFiles not being unpacked:\n'
463     for name in tar.getnames():
464         is_bad= 0
465         for r in exclude_re:
466             if r.match(name):
467                 is_bad=1
468                 if debug: print name
469                 break
470         if not is_bad:
471             good.append(tar.getmember(name))
472     if debug:
473         print '\nFiles being unpacked:\n'
474         for g in good:
475             print g
476     else:
477         tar.extractall(to_dir, good)
478
479 def my_winpybundle_print(target, source, env):
480     pass
481
482 def WinPyBundle(target=None, source=None, env=None):
483     import re
484     py_tar= env.subst( env['LCGDIR'] )
485     if py_tar[0]=='#':
486         py_tar= py_tar[1:]
487     if env['BF_DEBUG']:
488         py_tar+= '/release/python' + env['BF_PYTHON_VERSION'].replace('.','') + '_d.tar.gz'
489     else:
490         py_tar+= '/release/python' + env['BF_PYTHON_VERSION'].replace('.','') + '.tar.gz'
491
492     py_target = env.subst( env['BF_INSTALLDIR'] )
493     if py_target[0]=='#':
494         py_target=py_target[1:]
495     py_target = os.path.join(py_target, VERSION, 'python', 'lib')
496     def printexception(func,path,ex):
497         if os.path.exists(path): #do not report if path does not exist. eg on a fresh build.
498             print str(func) + ' failed on ' + str(path)
499     print "Trying to remove existing py bundle."
500     shutil.rmtree(py_target, False, printexception)
501     exclude_re=[re.compile('.*/test/.*'),
502                 re.compile('^config/.*'),
503                 re.compile('^config-*/.*'),
504                 re.compile('^distutils/.*'),
505                 re.compile('^idlelib/.*'),
506                 re.compile('^lib2to3/.*'),
507                 re.compile('^tkinter/.*'),
508                 re.compile('^_tkinter_d.pyd'),
509                 re.compile('^turtledemo'),
510                 re.compile('^turtle.py'),
511                 ]
512
513     print "Unpacking '" + py_tar + "' to '" + py_target + "'"
514     untar_pybundle(py_tar,py_target,exclude_re)
515
516 def  my_appit_print(target, source, env):
517     a = '%s' % (target[0])
518     d, f = os.path.split(a)
519     return "making bundle for " + f
520
521 def AppIt(target=None, source=None, env=None):
522     import shutil
523     import commands
524     import os.path
525     
526     
527     a = '%s' % (target[0])
528     builddir, b = os.path.split(a)
529     libdir = env['LCGDIR'][1:]
530     osxarch = env['MACOSX_ARCHITECTURE']
531     installdir = env['BF_INSTALLDIR']
532     print("compiled architecture: %s"%(osxarch))
533     print("Installing to %s"%(installdir))
534     # TODO, use tar.
535     python_zip = 'python_' + osxarch + '.zip' # set specific python_arch.zip
536     print("unzipping to app-bundle: %s"%(python_zip))
537     bldroot = env.Dir('.').abspath
538     binary = env['BINARYKIND']
539      
540     if b=='verse':
541         print bc.OKBLUE+"no bundle for verse"+bc.ENDC 
542         return 0
543     
544     sourcedir = bldroot + '/source/darwin/%s.app'%binary
545     sourceinfo = bldroot + "/source/darwin/%s.app/Contents/Info.plist"%binary
546     targetinfo = installdir +'/' + "%s.app/Contents/Info.plist"%binary
547     cmd = installdir + '/' +'%s.app'%binary
548     
549     if os.path.isdir(cmd):
550         shutil.rmtree(cmd)
551     shutil.copytree(sourcedir, cmd)
552     cmd = "cat %s | sed s/\$\{MACOSX_BUNDLE_SHORT_VERSION_STRING\}/%s/ | "%(sourceinfo,VERSION)
553     cmd += "sed s/\$\{MACOSX_BUNDLE_LONG_VERSION_STRING\}/%s,\ %s/g > %s"%(VERSION,time.strftime("%Y-%b-%d"),targetinfo)
554     commands.getoutput(cmd)
555     cmd = 'cp %s/%s %s/%s.app/Contents/MacOS/%s'%(builddir, binary,installdir, binary, binary)
556     commands.getoutput(cmd)
557     cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/'%(installdir, binary, VERSION)
558 #    print cmd
559     commands.getoutput(cmd)
560     cmd = installdir + '/%s.app/Contents/MacOS/%s'%(binary,VERSION)
561     shutil.copy(bldroot + '/release/bin/.blender/.bfont.ttf', cmd)
562     shutil.copy(bldroot + '/release/bin/.blender/.Blanguages', cmd)
563     cmd = 'cp -R %s/release/bin/%s/locale %s/%s.app/Contents/Resources/'%(bldroot,VERSION,installdir,binary)
564     commands.getoutput(cmd)
565     cmd = 'cp -R %s/release/bin/%s/locale %s/%s.app/Contents/MacOS/%s/'%(bldroot,VERSION,installdir,binary,VERSION)
566     commands.getoutput(cmd)
567     cmd = 'cp %s/release/bin/%s/.Blanguages %s/%s.app/Contents/Resources/'%(bldroot,VERSION,installdir,binary)
568     commands.getoutput(cmd)
569     cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/python/'%(installdir,binary, VERSION)
570     commands.getoutput(cmd)
571     cmd = 'unzip -q %s/release/%s -d %s/%s.app/Contents/MacOS/%s/python/'%(libdir,python_zip,installdir,binary,VERSION)
572     commands.getoutput(cmd)
573
574     if binary == 'blender':#not copy everything for blenderplayer
575         cmd = 'cp -R %s/release/scripts %s/%s.app/Contents/MacOS/%s/'%(bldroot,installdir,binary,VERSION)
576         commands.getoutput(cmd)
577         cmd = 'cp -R %s/release/ui %s/%s.app/Contents/MacOS/%s/'%(bldroot,installdir,binary,VERSION)
578         commands.getoutput(cmd)
579         cmd = 'cp -R %s/release/io %s/%s.app/Contents/MacOS/%s/'%(bldroot,installdir,binary,VERSION)
580         commands.getoutput(cmd)
581
582     cmd = 'chmod +x  %s/%s.app/Contents/MacOS/%s'%(installdir,binary, binary)
583     commands.getoutput(cmd)
584     cmd = 'find %s/%s.app -name .svn -prune -exec rm -rf {} \;'%(installdir, binary)
585     commands.getoutput(cmd)
586     cmd = 'find %s/%s.app -name .DS_Store -exec rm -rf {} \;'%(installdir, binary)
587     commands.getoutput(cmd)
588     cmd = 'find %s/%s.app -name __MACOSX -exec rm -rf {} \;'%(installdir, binary)
589     commands.getoutput(cmd)
590
591 # extract copy system python, be sure to update other build systems
592 # when making changes to the files that are copied.
593 def my_unixpybundle_print(target, source, env):
594     pass
595
596 def UnixPyBundle(target=None, source=None, env=None):
597     # Any Unix except osx
598     #-- VERSION/python/lib/python3.1
599     
600     import commands
601     
602     def run(cmd):
603         print 'Install command:', cmd
604         commands.getoutput(cmd)
605
606     dir = os.path.join(env['BF_INSTALLDIR'], VERSION)
607
608     py_src =    env.subst( env['BF_PYTHON_LIBPATH'] + '/python'+env['BF_PYTHON_VERSION'] )
609     py_target =    env.subst( dir + '/python/lib/python'+env['BF_PYTHON_VERSION'] )
610     
611     # This is a bit weak, but dont install if its been installed before, makes rebuilds quite slow.
612     if os.path.exists(py_target):
613         print 'Using existing python from:'
614         print '\t"%s"' %            py_target
615         print '\t(skipping copy)\n'
616         return
617
618     # Copied from source/creator/CMakeLists.txt, keep in sync.
619     print 'Install python from:'
620     print '\t"%s" into...' % py_src
621     print '\t"%s"\n' % py_target
622
623     run("rm -rf '%s'" % py_target)
624     try:
625         os.makedirs(os.path.dirname(py_target)) # the final part is copied
626     except:
627         pass
628
629     run("cp -R '%s' '%s'" % (py_src, os.path.dirname(py_target)))
630     run("rm -rf '%s/distutils'" % py_target)
631     run("rm -rf '%s/lib2to3'" % py_target)
632     run("rm -rf '%s/config'" % py_target)
633     run("rm -rf '%s/config-*'" % py_target)
634     run("rm -rf '%s/site-packages'" % py_target)
635     run("mkdir '%s/site-packages'" % py_target)    # python needs it.'
636     run("rm -rf '%s/idlelib'" % py_target)
637     run("rm -rf '%s/tkinter'" % py_target)
638     run("rm -rf '%s/turtledemo'" % py_target)
639     run("rm -r '%s/turtle.py'" % py_target)
640     run("rm -f '%s/lib-dynload/_tkinter.so'" % py_target)
641
642     run("find '%s' -type d -name 'test' -prune -exec rm -rf {} ';'" % py_target)
643     run("find '%s' -type d -name '__pycache__' -exec rm -rf {} ';'" % py_target)
644     run("find '%s' -name '*.py[co]' -exec rm -rf {} ';'" % py_target)
645     run("find '%s' -name '*.so' -exec strip -s {} ';'" % py_target)
646     
647
648 #### END ACTION STUFF #########
649
650 def bsc(env, target, source):
651     
652     bd = os.path.dirname(target[0].abspath)
653     bscfile = '\"'+target[0].abspath+'\"'
654     bscpathcollect = '\"'+bd + os.sep + '*.sbr\"'
655     bscpathtmp = '\"'+bd + os.sep + 'bscmake.tmp\"'
656
657     os.system('dir /b/s '+bscpathcollect+' >'+bscpathtmp)
658
659     myfile = open(bscpathtmp[1:-1], 'r')
660     lines = myfile.readlines()
661     myfile.close()
662
663     newfile = open(bscpathtmp[1:-1], 'w')
664     for l in lines:
665         newfile.write('\"'+l[:-1]+'\"\n')
666     newfile.close()
667                 
668     os.system('bscmake /nologo /n /o'+bscfile+' @'+bscpathtmp)
669     os.system('del '+bscpathtmp)
670
671 class BlenderEnvironment(SConsEnvironment):
672
673     PyBundleActionAdded = False
674
675     def BlenderRes(self=None, libname=None, source=None, libtype=['core'], priority=[100]):
676         global libs
677         if not self or not libname or not source:
678             print bc.FAIL+'Cannot continue.  Missing argument for BlenderRes '+libname+bc.ENDC
679             self.Exit()
680         if self['OURPLATFORM'] not in ('win32-vc','win32-mingw','linuxcross', 'win64-vc'):
681             print bc.FAIL+'BlenderRes is for windows only!'+bc.END
682             self.Exit()
683         
684         print bc.HEADER+'Configuring resource '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC
685         lenv = self.Clone()
686         if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
687             res = lenv.RES('#'+root_build_dir+'lib/'+libname, source)
688         else:
689             res = lenv.RES(root_build_dir+'lib/'+libname, source)
690
691         
692         SConsEnvironment.Default(self, res)
693         resources.append(res)
694
695     def BlenderLib(self=None, libname=None, sources=None, includes=[], defines=[], libtype='common', priority = 100, compileflags=None, cc_compileflags=None, cxx_compileflags=None):
696         global vcp
697         if not self or not libname or not sources:
698             print bc.FAIL+'Cannot continue. Missing argument for BuildBlenderLib '+libname+bc.ENDC
699             self.Exit()
700
701         def list_substring(quickie, libname):
702             for q in quickie:
703                 if libname.find(q) != -1:
704                     return True
705             return False
706
707         if list_substring(quickie, libname) or len(quickie)==0:
708             if list_substring(quickdebug, libname):
709                 print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname +bc.ENDC+bc.OKBLUE+ " (debug mode)" + bc.ENDC
710             else:
711                 print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname + bc.ENDC
712             lenv = self.Clone()
713             lenv.Append(CPPPATH=includes)
714             lenv.Append(CPPDEFINES=defines)
715             if lenv['BF_DEBUG'] or (libname in quickdebug):
716                     lenv.Append(CFLAGS = lenv['BF_DEBUG_CFLAGS'])
717                     lenv.Append(CCFLAGS = lenv['BF_DEBUG_CCFLAGS'])
718                     lenv.Append(CXXFLAGS = lenv['BF_DEBUG_CXXFLAGS'])
719             else:
720                     lenv.Append(CFLAGS = lenv['REL_CFLAGS'])
721                     lenv.Append(CCFLAGS = lenv['REL_CCFLAGS'])
722                     lenv.Append(CXXFLAGS = lenv['REL_CXXFLAGS'])
723             if lenv['BF_PROFILE']:
724                     lenv.Append(CFLAGS = lenv['BF_PROFILE_CFLAGS'])
725                     lenv.Append(CCFLAGS = lenv['BF_PROFILE_CCFLAGS'])
726                     lenv.Append(CXXFLAGS = lenv['BF_PROFILE_CXXFLAGS'])
727             if compileflags:
728                 lenv.Replace(CFLAGS = compileflags)
729             if cc_compileflags:
730                 lenv.Replace(CCFLAGS = cc_compileflags)
731             if cxx_compileflags:
732                 lenv.Replace(CXXFLAGS = cxx_compileflags)
733             lenv.Append(CFLAGS = lenv['C_WARN'])
734             lenv.Append(CCFLAGS = lenv['CC_WARN'])
735             lenv.Append(CXXFLAGS = lenv['CXX_WARN'])
736
737             if lenv['OURPLATFORM'] == 'win64-vc':
738                 lenv.Append(LINKFLAGS = ['/MACHINE:X64'])
739
740             if lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
741                 if lenv['BF_DEBUG']:
742                     lenv.Append(CCFLAGS = ['/MTd'])
743                 else:
744                     lenv.Append(CCFLAGS = ['/MT'])
745             
746             targetdir = root_build_dir+'lib/' + libname
747             if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
748                 targetdir = '#'+targetdir
749             lib = lenv.Library(target= targetdir, source=sources)
750             SConsEnvironment.Default(self, lib) # we add to default target, because this way we get some kind of progress info during build
751             if self['BF_MSVS'] and self['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
752                 #if targetdir[0] == '#':
753                 #    targetdir = targetdir[1:-1]
754                 print "! ",targetdir+ '.vcproj' # + self['MSVSPROJECTSUFFIX']
755                 vcproject = self.MSVSProject(target = targetdir + '.vcproj', # + self['MSVSPROJECTSUFFIX'],
756                          srcs = sources,
757                          buildtarget = lib,
758                          variant = 'Release',
759                          auto_build_solution=0)
760                 vcp.append(vcproject)
761                 SConsEnvironment.Default(self, vcproject)
762         else:
763             print bc.WARNING+'Not building '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC+' for '+bc.OKBLUE+'BF_QUICK'+bc.ENDC
764         # note: libs is a global
765         add_lib_to_dict(self, libs, libtype, libname, priority)
766
767     def BlenderProg(self=None, builddir=None, progname=None, sources=None, libs=None, libpath=None, binarykind=''):
768         global vcp
769         print bc.HEADER+'Configuring program '+bc.ENDC+bc.OKGREEN+progname+bc.ENDC
770         lenv = self.Clone()
771         lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
772         if lenv['OURPLATFORM'] in ('win32-vc', 'cygwin', 'win64-vc'):
773             if lenv['BF_DEBUG']:
774                 lenv.Prepend(LINKFLAGS = ['/DEBUG','/PDB:'+progname+'.pdb','/NODEFAULTLIB:libcmt'])
775         if  lenv['OURPLATFORM']=='linux2':
776             if lenv['WITH_BF_PYTHON']:
777                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
778         if  lenv['OURPLATFORM']=='sunos5':
779             if lenv['WITH_BF_PYTHON']:
780                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
781             if lenv['CXX'].endswith('CC'):
782                  lenv.Replace(LINK = '$CXX')
783         if  lenv['OURPLATFORM']=='darwin':
784             if lenv['WITH_BF_PYTHON']:
785                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
786             lenv.Append(LINKFLAGS = lenv['BF_OPENGL_LINKFLAGS'])
787         if lenv['BF_PROFILE']:
788             lenv.Append(LINKFLAGS = lenv['BF_PROFILE_LINKFLAGS'])
789         if root_build_dir[0]==os.sep or root_build_dir[1]==':':
790             lenv.Append(LIBPATH=root_build_dir + '/lib')
791         lenv.Append(LIBPATH=libpath)
792         lenv.Append(LIBS=libs)
793         if lenv['WITH_BF_QUICKTIME']:
794              lenv.Append(LIBS = lenv['BF_QUICKTIME_LIB'])
795              lenv.Append(LIBPATH = lenv['BF_QUICKTIME_LIBPATH'])
796         prog = lenv.Program(target=builddir+'bin/'+progname, source=sources)
797         if lenv['BF_DEBUG'] and lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc') and lenv['BF_BSC']:
798             f = lenv.File(progname + '.bsc', builddir)
799             brs = lenv.Command(f, prog, [bsc])
800             SConsEnvironment.Default(self, brs)
801         SConsEnvironment.Default(self, prog)
802         if self['BF_MSVS'] and self['OURPLATFORM'] in ('win32-vc', 'win64-vc') and progname == 'blender':
803             print "! ",builddir + "/" + progname + '.sln'
804             sln = self.MSVSProject(target = builddir + "/" + progname + '.sln',
805                      projects= vcp,
806                      variant = 'Release')
807             SConsEnvironment.Default(self, sln)
808         program_list.append(prog)
809         if  lenv['OURPLATFORM']=='darwin':
810             lenv['BINARYKIND'] = binarykind
811             lenv.AddPostAction(prog,Action(AppIt,strfunction=my_appit_print))
812         elif os.sep == '/' and lenv['OURPLATFORM'] != 'linuxcross': # any unix (except cross-compilation)
813             if lenv['WITH_BF_PYTHON']:
814                 if not lenv['WITHOUT_BF_INSTALL'] and not lenv['WITHOUT_BF_PYTHON_INSTALL'] and not BlenderEnvironment.PyBundleActionAdded:
815                     lenv.AddPostAction(prog,Action(UnixPyBundle,strfunction=my_unixpybundle_print))
816                     BlenderEnvironment.PyBundleActionAdded = True
817         elif lenv['OURPLATFORM'].startswith('win') or lenv['OURPLATFORM'] == 'linuxcross': # windows or cross-compilation
818             if lenv['WITH_BF_PYTHON']:
819                 if not lenv['WITHOUT_BF_PYTHON_INSTALL'] and not BlenderEnvironment.PyBundleActionAdded:
820                     lenv.AddPostAction(prog,Action(WinPyBundle,strfunction=my_winpybundle_print))
821                     BlenderEnvironment.PyBundleActionAdded = True
822         return prog
823
824     def Glob(lenv, pattern):
825         path = string.replace(GetBuildPath(lenv,'SConscript'),'SConscript', '')
826         files = []
827         for i in glob.glob(path + pattern):
828             files.append(string.replace(i, path, ''))
829         return files