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