Python: Remove deprecated uses of os.popen
[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 string
19 import ctypes as ct
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.Subst
33 import SCons.Tool
34 import bcolors
35 bc = bcolors.bcolors()
36 import btools
37 VERSION = btools.VERSION
38 VERSION_RELEASE_CYCLE = btools.VERSION_RELEASE_CYCLE
39
40 Split = SCons.Util.Split
41 Action = SCons.Action.Action
42 Builder = SCons.Builder.Builder
43 GetBuildPath = SConsEnvironment.GetBuildPath
44
45 # a few globals
46 root_build_dir = ''
47 doc_build_dir = ''
48 quickie = None # Anything else than None if BF_QUICK has been passed
49 quicklist = [] # The list of libraries/programs to compile during a quickie
50 program_list = [] # A list holding Nodes to final binaries, used to create installs
51 arguments = None
52 targets = None
53 resources = []
54 allowed_bitnesses = {4 : 32, 8 : 64} # only expecting 32-bit or 64-bit
55 bitness = allowed_bitnesses[ct.sizeof(ct.c_void_p)]
56
57 ##### LIB STUFF ##########
58
59 possible_types = ['core'] # can be set in ie. SConstruct
60 libs = {}
61 vcp = []
62
63 def getresources():
64     return resources
65
66 def init_lib_dict():
67     for pt in possible_types:
68         libs[pt] = {}
69
70 # helper func for add_lib_to_dict
71 def internal_lib_to_dict(dict = None, libtype = None, libname = None, priority = 100):
72     if not libname in dict[libtype]:
73         done = None
74         while not done:
75             if dict[libtype].has_key(priority):
76                 priority = priority + 1
77             else:
78                 done = True
79         dict[libtype][priority] = libname
80
81 # libtype and priority can both be lists, for defining lib in multiple places
82 def add_lib_to_dict(env, dict = None, libtype = None, libname = None, priority = 100):
83     if not dict or not libtype or not libname:
84         print "Passed wrong arg"
85         env.Exit()
86
87     if type(libtype) is str and type(priority) is int:
88         internal_lib_to_dict(dict, libtype, libname, priority)
89     elif type(libtype) is list and type(priority) is list:
90         if len(libtype)==len(priority):
91             for lt, p in zip(libtype, priority):
92                 internal_lib_to_dict(dict, lt, libname, p)
93         else:
94             print "libtype and priority lists are unequal in length"
95             env.Exit()
96     else:
97         print "Wrong type combinations for libtype and priority. Only str and int or list and list"
98         env.Exit()
99
100 def create_blender_liblist(lenv = None, libtype = None):
101     if not lenv or not libtype:
102         print "missing arg"
103
104     lst = []
105     if libtype in possible_types:
106         curlib = libs[libtype]
107         sortlist = curlib.keys()
108         sortlist.sort()
109         for sk in sortlist:
110             v = curlib[sk]
111             if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
112                 target = os.path.abspath(os.getcwd() + os.sep + root_build_dir + 'lib' + os.sep +lenv['LIBPREFIX'] + v + lenv['LIBSUFFIX'])
113             else:
114                 target = os.path.abspath(root_build_dir + 'lib' + os.sep +lenv['LIBPREFIX'] + v + lenv['LIBSUFFIX'])
115             lst.append(target)
116
117     return lst
118
119 ## TODO: static linking
120 def setup_staticlibs(lenv):
121     statlibs = [
122         #here libs for static linking
123     ]
124
125     libincs = []
126
127     if lenv['WITH_BF_FFMPEG']:
128         libincs += Split(lenv['BF_FFMPEG_LIBPATH'])
129
130     libincs.extend([
131         lenv['BF_OPENGL_LIBPATH'],
132         lenv['BF_JPEG_LIBPATH'],
133         lenv['BF_ZLIB_LIBPATH'],
134         lenv['BF_PNG_LIBPATH'],
135         lenv['BF_ICONV_LIBPATH']
136         ])
137
138     if lenv['WITH_BF_STATICJPEG']:
139         statlibs += Split(lenv['BF_JPEG_LIB_STATIC'])
140     if lenv['WITH_BF_STATICPNG']:
141         statlibs += Split(lenv['BF_PNG_LIB_STATIC'])
142
143     libincs += Split(lenv['BF_FREETYPE_LIBPATH'])
144     if lenv['WITH_BF_PYTHON']:
145         libincs += Split(lenv['BF_PYTHON_LIBPATH'])
146     if lenv['WITH_BF_SDL']:
147         libincs += Split(lenv['BF_SDL_LIBPATH'])
148     if lenv['WITH_BF_JACK'] and not lenv['WITH_BF_JACK_DYNLOAD']:
149         libincs += Split(lenv['BF_JACK_LIBPATH'])
150     if lenv['WITH_BF_SNDFILE']:
151         libincs += Split(lenv['BF_SNDFILE_LIBPATH'])
152     if lenv['WITH_BF_TIFF']:
153         libincs += Split(lenv['BF_TIFF_LIBPATH'])
154         if lenv['WITH_BF_STATICTIFF']:
155             statlibs += Split(lenv['BF_TIFF_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     '''
161     if lenv['WITH_BF_ELTOPO']:
162         libincs += Split(lenv['BF_LAPACK_LIBPATH'])
163         if lenv['WITH_BF_STATICLAPACK']:
164             statlibs += Split(lenv['BF_LAPACK_LIB_STATIC'])
165     '''
166     if lenv['WITH_BF_FFMPEG'] and lenv['WITH_BF_STATICFFMPEG']:
167         statlibs += Split(lenv['BF_FFMPEG_LIB_STATIC'])
168     if lenv['WITH_BF_INTERNATIONAL']:
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', 'win64-mingw'):
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', 'win64-mingw'):
192             libincs += Split(lenv['BF_PCRE_LIBPATH'])
193             libincs += Split(lenv['BF_EXPAT_LIBPATH'])
194         if lenv['WITH_BF_STATICOPENCOLLADA']:
195             statlibs += Split(lenv['BF_OPENCOLLADA_LIB_STATIC'])
196
197     if lenv['WITH_BF_OPENMP']:
198         if lenv['OURPLATFORM'] == 'linuxcross':
199             libincs += Split(lenv['BF_OPENMP_LIBPATH'])
200         if lenv['WITH_BF_STATICOPENMP']:
201             statlibs += Split(lenv['BF_OPENMP_LIB_STATIC'])
202             
203     if lenv['WITH_BF_OIIO']:
204         libincs += Split(lenv['BF_OIIO_LIBPATH'])
205         if lenv['WITH_BF_STATICOIIO']:
206             statlibs += Split(lenv['BF_OIIO_LIB_STATIC'])
207     if lenv['WITH_BF_OPENEXR']:
208         libincs += Split(lenv['BF_OPENEXR_LIBPATH'])
209         if lenv['WITH_BF_STATICOPENEXR']:
210             statlibs += Split(lenv['BF_OPENEXR_LIB_STATIC'])
211     if lenv['WITH_BF_ZLIB'] and lenv['WITH_BF_STATICZLIB']:
212         statlibs += Split(lenv['BF_ZLIB_LIB_STATIC'])
213
214     if lenv['WITH_BF_OCIO']:
215         libincs += Split(lenv['BF_OCIO_LIBPATH'])
216         if lenv['WITH_BF_STATICOCIO']:
217             statlibs += Split(lenv['BF_OCIO_LIB_STATIC'])
218
219     if lenv['WITH_BF_BOOST']:
220         libincs += Split(lenv['BF_BOOST_LIBPATH'])
221         if lenv['WITH_BF_STATICBOOST']:
222             statlibs += Split(lenv['BF_BOOST_LIB_STATIC'])
223
224     if lenv['WITH_BF_CYCLES_OSL']:
225         libincs += Split(lenv['BF_OSL_LIBPATH'])
226         if lenv['WITH_BF_STATICOSL']:
227             statlibs += Split(lenv['BF_OSL_LIB_STATIC'])
228
229     if lenv['WITH_BF_LLVM']:
230         libincs += Split(lenv['BF_LLVM_LIBPATH'])
231         if lenv['WITH_BF_STATICLLVM']:
232             statlibs += Split(lenv['BF_LLVM_LIB_STATIC'])
233
234     if lenv['WITH_BF_JEMALLOC']:
235         libincs += Split(lenv['BF_JEMALLOC_LIBPATH'])
236         if lenv['WITH_BF_STATICJEMALLOC']:
237             statlibs += Split(lenv['BF_JEMALLOC_LIB_STATIC'])
238
239     if lenv['OURPLATFORM']=='linux':
240         if lenv['WITH_BF_3DMOUSE']:
241             libincs += Split(lenv['BF_3DMOUSE_LIBPATH'])
242             if lenv['WITH_BF_STATIC3DMOUSE']:
243                 statlibs += Split(lenv['BF_3DMOUSE_LIB_STATIC'])
244
245     # setting this last so any overriding of manually libs could be handled
246     if lenv['OURPLATFORM'] not in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross', 'win64-mingw'):
247         # We must remove any previous items defining this path, for same reason stated above!
248         libincs = [e for e in libincs if SCons.Subst.scons_subst(e, lenv, gvars=lenv.Dictionary()) != "/usr/lib"]
249         libincs.append('/usr/lib')
250
251     return statlibs, libincs
252
253 def setup_syslibs(lenv):
254     syslibs = []
255
256     if not lenv['WITH_BF_FREETYPE_STATIC']:
257         syslibs += Split(lenv['BF_FREETYPE_LIB'])
258     if lenv['WITH_BF_PYTHON'] and not lenv['WITH_BF_STATICPYTHON']:
259         if lenv['BF_DEBUG'] and lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc', 'win32-mingw', 'win64-mingw'):
260             syslibs.append(lenv['BF_PYTHON_LIB']+'_d')
261         else:
262             syslibs.append(lenv['BF_PYTHON_LIB'])
263     if lenv['WITH_BF_OPENAL']:
264         if not lenv['WITH_BF_STATICOPENAL']:
265             syslibs += Split(lenv['BF_OPENAL_LIB'])
266     if lenv['WITH_BF_OPENMP'] and lenv['CC'] != 'icc' and lenv['C_COMPILER_ID'] != 'clang' and not lenv['WITH_BF_STATICOPENMP']:
267         if lenv['CC'] == 'cl.exe':
268             syslibs += ['vcomp']
269         else:
270             syslibs += ['gomp']
271     if lenv['WITH_BF_ICONV']:
272         syslibs += Split(lenv['BF_ICONV_LIB'])
273     if lenv['WITH_BF_OIIO']:
274         if not lenv['WITH_BF_STATICOIIO']:
275             syslibs += Split(lenv['BF_OIIO_LIB'])
276
277     if lenv['WITH_BF_OCIO']:
278         if not lenv['WITH_BF_STATICOCIO']:
279             syslibs += Split(lenv['BF_OCIO_LIB'])
280
281     if lenv['WITH_BF_OPENEXR'] and not lenv['WITH_BF_STATICOPENEXR']:
282         syslibs += Split(lenv['BF_OPENEXR_LIB'])
283     if lenv['WITH_BF_ZLIB'] and not lenv['WITH_BF_STATICZLIB']:
284         syslibs += Split(lenv['BF_ZLIB_LIB'])
285     if lenv['WITH_BF_TIFF'] and not lenv['WITH_BF_STATICTIFF']:
286         syslibs += Split(lenv['BF_TIFF_LIB'])
287     if lenv['WITH_BF_FFMPEG'] and not lenv['WITH_BF_STATICFFMPEG']:
288         syslibs += Split(lenv['BF_FFMPEG_LIB'])
289         if lenv['WITH_BF_OGG']:
290             syslibs += Split(lenv['BF_OGG_LIB'])
291     if lenv['WITH_BF_JACK'] and not lenv['WITH_BF_JACK_DYNLOAD']:
292         syslibs += Split(lenv['BF_JACK_LIB'])
293     if lenv['WITH_BF_SNDFILE'] and not lenv['WITH_BF_STATICSNDFILE']:
294         syslibs += Split(lenv['BF_SNDFILE_LIB'])
295     if lenv['WITH_BF_FFTW3'] and not lenv['WITH_BF_STATICFFTW3']:
296         syslibs += Split(lenv['BF_FFTW3_LIB'])
297     '''
298     if lenv['WITH_BF_ELTOPO']:
299         syslibs += Split(lenv['BF_LAPACK_LIB'])
300     '''
301     if lenv['WITH_BF_SDL']:
302         syslibs += Split(lenv['BF_SDL_LIB'])
303     if not lenv['WITH_BF_STATICOPENGL']:
304         syslibs += Split(lenv['BF_OPENGL_LIB'])
305     if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw','linuxcross', 'win64-vc', 'win64-mingw'):
306         syslibs += Split(lenv['BF_PTHREADS_LIB'])
307     if lenv['WITH_BF_COLLADA'] and not lenv['WITH_BF_STATICOPENCOLLADA']:
308         syslibs.append(lenv['BF_PCRE_LIB'])
309         if lenv['BF_DEBUG'] and (lenv['OURPLATFORM'] != 'linux'):
310             syslibs += [colladalib+'_d' for colladalib in Split(lenv['BF_OPENCOLLADA_LIB'])]
311         else:
312             syslibs += Split(lenv['BF_OPENCOLLADA_LIB'])
313         syslibs.append(lenv['BF_EXPAT_LIB'])
314
315     if lenv['WITH_BF_JEMALLOC']:
316         if not lenv['WITH_BF_STATICJEMALLOC']:
317             syslibs += Split(lenv['BF_JEMALLOC_LIB'])
318
319     if lenv['OURPLATFORM']=='linux':
320         if lenv['WITH_BF_3DMOUSE']:
321             if not lenv['WITH_BF_STATIC3DMOUSE']:
322                 syslibs += Split(lenv['BF_3DMOUSE_LIB'])
323                 
324     if lenv['WITH_BF_BOOST'] and not lenv['WITH_BF_STATICBOOST']:
325         syslibs += Split(lenv['BF_BOOST_LIB'])
326         
327         if lenv['WITH_BF_INTERNATIONAL']:
328             syslibs += Split(lenv['BF_BOOST_LIB_INTERNATIONAL'])
329
330     if lenv['WITH_BF_CYCLES_OSL'] and not lenv['WITH_BF_STATICOSL']:
331         syslibs += Split(lenv['BF_OSL_LIB'])
332
333     if lenv['WITH_BF_LLVM'] and not lenv['WITH_BF_STATICLLVM']:
334         syslibs += Split(lenv['BF_LLVM_LIB'])
335
336     if not lenv['WITH_BF_STATICJPEG']:
337         syslibs += Split(lenv['BF_JPEG_LIB'])
338
339     if not lenv['WITH_BF_STATICPNG']:
340         syslibs += Split(lenv['BF_PNG_LIB'])
341
342     syslibs += lenv['LLIBS']
343
344     return syslibs
345
346 def propose_priorities():
347     print bc.OKBLUE+"Priorities:"+bc.ENDC
348     for t in possible_types:
349         print bc.OKGREEN+"\t"+t+bc.ENDC
350         new_priority = 0
351         curlib = libs[t]
352         sortlist = curlib.keys()
353         sortlist.sort()
354
355         for sk in sortlist:
356             v = curlib[sk]
357             #for p,v in sorted(libs[t].iteritems()):
358             print "\t\t",new_priority, v
359             new_priority += 5
360
361 # emits the necessary file objects for creator.c, to be used in creating
362 # the final blender executable
363 def creator(env):
364     sources = ['creator.c']# + Blender.buildinfo(env, "dynamic") + Blender.resources
365
366     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']]
367
368     defs = []
369
370     if env['WITH_BF_BINRELOC']:
371         incs.append('#/extern/binreloc/include')
372         defs.append('WITH_BINRELOC')
373
374     if env['WITH_BF_SDL']:
375         defs.append('WITH_SDL')
376
377     if env['WITH_BF_LIBMV']:
378         incs.append('#/extern/libmv')
379         defs.append('WITH_LIBMV')
380
381     if env['WITH_BF_FFMPEG']:
382         defs.append('WITH_FFMPEG')
383
384     if env['WITH_BF_PYTHON']:
385         incs.append('#/source/blender/python')
386         defs.append('WITH_PYTHON')
387         if env['BF_DEBUG']:
388             defs.append('_DEBUG')
389
390     if env['WITH_BF_FREESTYLE']:
391         incs.append('#/source/blender/freestyle')
392         defs.append('WITH_FREESTYLE')
393
394     if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
395         incs.append(env['BF_PTHREADS_INC'])
396         incs.append('#/intern/utfconv')
397
398     env.Append(CPPDEFINES=defs)
399     env.Append(CPPPATH=incs)
400     obj = [env.Object(root_build_dir+'source/creator/creator/creator', ['#source/creator/creator.c'])]
401
402     return obj
403
404 ## TODO: see if this can be made in an emitter
405 def buildinfo(lenv, build_type):
406     """
407     Generate a buildinfo object
408     """
409     import subprocess
410
411     build_date = time.strftime ("%Y-%m-%d")
412     build_time = time.strftime ("%H:%M:%S")
413
414     if os.path.isdir(os.path.abspath('.git')):
415         build_commit_timestamp = subprocess.check_output(args=['git', 'log', '-1', '--format=%ct']).strip()
416         if not build_commit_timestamp:
417             # Git command not found
418             build_hash = 'unknown'
419             build_commit_timestamp = '0'
420             build_branch = 'unknown'
421         else:
422             no_upstream = False
423
424             try :
425                 build_hash = subprocess.check_output(['git', 'rev-parse', '--short', '@{u}']).strip()
426             except subprocess.CalledProcessError:
427                 # assume branch has no upstream configured
428                 build_hash = ''
429
430             build_branch = subprocess.check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD']).strip()
431
432             if build_branch == 'HEAD':
433                 master_check = subprocess.check_output(['git', 'branch', '--list', 'master', '--contains', build_hash]).strip()
434                 if master_check == 'master':
435                     build_branch = 'master'
436                 else:
437                     head_hash = subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip()
438                     tag_hashes = subprocess.check_output(['git', 'show-ref', '--tags', '-d'])
439                     if tag_hashes.find(head_hash) != -1:
440                         build_branch = 'master'
441
442             if build_hash == '':
443                 build_hash = subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD']).strip()
444                 no_upstream = True
445             else:
446                 older_commits = subprocess.check_output(['git', 'log', '--oneline', 'HEAD..@{u}']).strip()
447                 if older_commits:
448                     build_hash = subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD']).strip()
449
450             # ## Check for local modifications
451             has_local_changes = False
452
453             # Update GIT index before getting dirty files
454             os.system('git update-index -q --refresh')
455             changed_files = subprocess.check_output(['git', 'diff-index', '--name-only', 'HEAD', '--']).strip()
456
457             if changed_files:
458                 has_local_changes = True
459             elif no_upstream == False:
460                 unpushed_log = subprocess.check_output(['git', 'log', '--oneline', '@{u}..']).strip()
461                 has_local_changes = unpushed_log != ''
462
463             if build_branch.startswith('blender-v'):
464                 build_branch = 'master'
465
466             if has_local_changes:
467                 build_branch += ' (modified)'
468     else:
469         build_hash = 'unknown'
470         build_commit_timestamp = '0'
471         build_branch = 'unknown'
472
473     if lenv['BF_DEBUG']:
474         build_type = "Debug"
475         build_cflags = ' '.join(lenv['CFLAGS'] + lenv['CCFLAGS'] + lenv['BF_DEBUG_CCFLAGS'] + lenv['CPPFLAGS'])
476         build_cxxflags = ' '.join(lenv['CCFLAGS'] + lenv['CXXFLAGS'] + lenv['CPPFLAGS'])
477     else:
478         build_type = "Release"
479         build_cflags = ' '.join(lenv['CFLAGS'] + lenv['CCFLAGS'] + lenv['REL_CFLAGS'] + lenv['REL_CCFLAGS'] + lenv['CPPFLAGS'])
480         build_cxxflags = ' '.join(lenv['CCFLAGS'] + lenv['CXXFLAGS'] + lenv['REL_CXXFLAGS'] + lenv['REL_CCFLAGS'] + lenv['CPPFLAGS'])
481
482     build_linkflags = ' '.join(lenv['PLATFORM_LINKFLAGS'])
483
484     obj = []
485     if lenv['BF_BUILDINFO']:
486         lenv.Append (CPPDEFINES = ['BUILD_TIME=\\"%s\\"'%(build_time),
487                                     'BUILD_DATE=\\"%s\\"'%(build_date),
488                                     'BUILD_TYPE=\\"%s\\"'%(build_type),
489                                     'BUILD_HASH=\\"%s\\"'%(build_hash),
490                                     'BUILD_COMMIT_TIMESTAMP=%s'%(build_commit_timestamp),
491                                     'BUILD_BRANCH=\\"%s\\"'%(build_branch),
492                                     'WITH_BUILDINFO',
493                                     'BUILD_PLATFORM=\\"%s:%s\\"'%(platform.system(), platform.architecture()[0]),
494                                     'BUILD_CFLAGS=\\"%s\\"'%(build_cflags),
495                                     'BUILD_CXXFLAGS=\\"%s\\"'%(build_cxxflags),
496                                     'BUILD_LINKFLAGS=\\"%s\\"'%(build_linkflags),
497                                     'BUILD_SYSTEM=\\"SCons\\"'
498                     ])
499
500         lenv.Append (CPPPATH = [root_build_dir+'source/blender/blenkernel'])
501
502         obj = [lenv.Object (root_build_dir+'source/creator/%s_buildinfo'%build_type, ['#source/creator/buildinfo.c'])]
503
504     return obj
505
506 ##### END LIB STUFF ############
507
508 ##### ACTION STUFF #############
509
510 def my_print_cmd_line(self, s, target, source, env):
511     sys.stdout.write(' ' * 70 + '\r')
512     sys.stdout.flush()
513     sys.stdout.write(s + "\r")
514     sys.stdout.flush()
515
516 def my_compile_print(target, source, env):
517     a = '%s' % (source[0])
518     d, f = os.path.split(a)
519     return bc.OKBLUE + "Compiling" + bc.ENDC + " ==> '" + bc.OKGREEN + ("%s" % f) + bc.ENDC + "'"
520
521 def my_moc_print(target, source, env):
522     a = '%s' % (source[0])
523     d, f = os.path.split(a)
524     return bc.OKBLUE + "Creating MOC" + bc.ENDC + " ==> '" + bc.OKGREEN + ("%s" % f) + bc.ENDC + "'"
525
526 def my_linking_print(target, source, env):
527     t = '%s' % (target[0])
528     d, f = os.path.split(t)
529     return bc.OKBLUE + "Linking library" + bc.ENDC + " ==> '" + bc.OKGREEN + ("%s" % f) + bc.ENDC + "'"
530
531 def my_program_print(target, source, env):
532     t = '%s' % (target[0])
533     d, f = os.path.split(t)
534     return bc.OKBLUE + "Linking program" + bc.ENDC + " ==> '" + bc.OKGREEN + ("%s" % f) + bc.ENDC + "'"
535
536 def msvc_hack(env):
537     static_lib = SCons.Tool.createStaticLibBuilder(env)
538     program = SCons.Tool.createProgBuilder(env)
539     
540     env['BUILDERS']['Library'] = static_lib
541     env['BUILDERS']['StaticLibrary'] = static_lib
542     env['BUILDERS']['Program'] = program
543         
544 def set_quiet_output(env):
545     mycaction = Action("$CCCOM", strfunction=my_compile_print)
546     myshcaction = Action("$SHCCCOM", strfunction=my_compile_print)
547     mycppaction = Action("$CXXCOM", strfunction=my_compile_print)
548     myshcppaction = Action("$SHCXXCOM", strfunction=my_compile_print)
549     mylibaction = Action("$ARCOM", strfunction=my_linking_print)
550     mylinkaction = Action("$LINKCOM", strfunction=my_program_print)
551
552     static_ob, shared_ob = SCons.Tool.createObjBuilders(env)
553     static_ob.add_action('.c', mycaction)
554     static_ob.add_action('.cpp', mycppaction)
555     static_ob.add_action('.cc', mycppaction)
556     shared_ob.add_action('.c', myshcaction)
557     shared_ob.add_action('.cc', myshcppaction)
558
559     static_lib = SCons.Builder.Builder(action = mylibaction,
560                                        emitter = '$LIBEMITTER',
561                                        prefix = '$LIBPREFIX',
562                                        suffix = '$LIBSUFFIX',
563                                        src_suffix = '$OBJSUFFIX',
564                                        src_builder = 'StaticObject')
565
566     program = SCons.Builder.Builder(action = mylinkaction,
567                                     emitter = '$PROGEMITTER',
568                                     prefix = '$PROGPREFIX',
569                                     suffix = '$PROGSUFFIX',
570                                     src_suffix = '$OBJSUFFIX',
571                                     src_builder = 'Object',
572                                     target_scanner = SCons.Defaults.ProgScan)
573
574     env['BUILDERS']['Object'] = static_ob
575     env['BUILDERS']['StaticObject'] = static_ob
576     env['BUILDERS']['StaticLibrary'] = static_lib
577     env['BUILDERS']['Library'] = static_lib
578     env['BUILDERS']['Program'] = program
579     if env['BF_LINE_OVERWRITE']:
580         SCons.Action._ActionAction.print_cmd_line = my_print_cmd_line
581
582 def untar_pybundle(from_tar,to_dir,exclude_re):
583     tar= tarfile.open(from_tar, mode='r')
584     exclude_re= list(exclude_re) #single re object or list of re objects
585     debug= 0 #list files instead of unpacking
586     good= []
587     if debug: print '\nFiles not being unpacked:\n'
588     for name in tar.getnames():
589         is_bad= 0
590         for r in exclude_re:
591             if r.match(name):
592                 is_bad=1
593                 if debug: print name
594                 break
595         if not is_bad:
596             good.append(tar.getmember(name))
597     if debug:
598         print '\nFiles being unpacked:\n'
599         for g in good:
600             print g
601     else:
602         tar.extractall(to_dir, good)
603
604 def my_winpybundle_print(target, source, env):
605     pass
606
607 def WinPyBundle(target=None, source=None, env=None):
608     import re
609     py_tar = env.subst(env['LCGDIR']).lstrip("#")
610     if env['BF_DEBUG']:
611         py_tar+= '/release/python' + env['BF_PYTHON_VERSION'].replace('.','') + '_d.tar.gz'
612     else:
613         py_tar+= '/release/python' + env['BF_PYTHON_VERSION'].replace('.','') + '.tar.gz'
614
615     py_target = env.subst(env['BF_INSTALLDIR']).lstrip("#")
616     py_target = os.path.join(py_target, VERSION, 'python', 'lib')
617     def printexception(func,path,ex):
618         if os.path.exists(path): #do not report if path does not exist. eg on a fresh build.
619             print str(func) + ' failed on ' + str(path)
620     print "Trying to remove existing py bundle."
621     shutil.rmtree(py_target, False, printexception)
622     exclude_re=[re.compile('.*/test'),
623                 re.compile('^test'),
624                 re.compile('^distutils'),
625                 re.compile('^idlelib'),
626                 re.compile('^lib2to3'),
627                 re.compile('^tkinter'),
628                 re.compile('^_tkinter_d.pyd'),
629                 re.compile('^turtledemo'),
630                 re.compile('^turtle.py'),
631                 ]
632
633     print "Unpacking '" + py_tar + "' to '" + py_target + "'"
634     untar_pybundle(py_tar,py_target,exclude_re)
635
636     # -------------
637     # Extract Numpy
638     if env['WITH_BF_PYTHON_INSTALL_NUMPY']:
639         py_tar = env.subst(env['LCGDIR']).lstrip("#")
640         py_tar += '/release/python' + env['BF_PYTHON_VERSION'].replace('.','') + '_numpy_1.8.tar.gz'
641
642         py_target = env.subst(env['BF_INSTALLDIR']).lstrip("#")
643         py_target = os.path.join(py_target, VERSION, 'python', 'lib', 'site-packages')
644         # rmtree handled above
645         # files are cleaned up in their archive
646         exclude_re = []
647         print("Unpacking '" + py_tar + "' to '" + py_target + "'")
648         untar_pybundle(py_tar, py_target, exclude_re)
649
650     # --------------------
651     # Copy 'site-packages'
652     py_dir = env.subst(env['LCGDIR']).lstrip("#")
653     py_dir += '/release/site-packages'
654     # grr, we have to do one by one because the dir exists
655     for f in os.listdir(py_dir):
656         fn_src = os.path.join(py_dir, f)
657         fn_dst = os.path.join(py_target, f)
658
659         shutil.rmtree(fn_dst, False, printexception)
660         shutil.copytree(fn_src, fn_dst)
661
662
663
664 def  my_appit_print(target, source, env):
665     a = '%s' % (target[0])
666     d, f = os.path.split(a)
667     return "making bundle for " + f
668
669 def AppIt(target=None, source=None, env=None):
670     import shutil
671     import commands
672     import os.path
673     
674     
675     a = '%s' % (target[0])
676     builddir, b = os.path.split(a)
677     libdir = env['LCGDIR'][1:]
678     osxarch = env['MACOSX_ARCHITECTURE']
679     installdir = env['BF_INSTALLDIR']
680     print("compiled architecture: %s"%(osxarch))
681     print("Installing to %s"%(installdir))
682     # TODO, use tar.
683     python_zip = 'python_' + osxarch + '.zip' # set specific python_arch.zip
684     if env['WITH_OSX_STATICPYTHON']:
685         print("unzipping to app-bundle: %s"%(python_zip))
686     else:
687         print("dynamic build - make sure to have python3.x-framework installed")
688     bldroot = env.Dir('.').abspath
689     binary = env['BINARYKIND']
690      
691     sourcedir = bldroot + '/release/darwin/%s.app' % binary
692     sourceinfo = bldroot + "/release/darwin/%s.app/Contents/Info.plist"%binary
693     targetinfo = installdir +'/' + "%s.app/Contents/Info.plist"%binary
694     cmd = installdir + '/' +'%s.app'%binary
695     
696     if os.path.isdir(cmd):
697         shutil.rmtree(cmd)
698     shutil.copytree(sourcedir, cmd)
699     cmd = "cat %s | sed s/\$\{MACOSX_BUNDLE_SHORT_VERSION_STRING\}/%s/ | "%(sourceinfo,VERSION)
700     cmd += "sed s/\$\{MACOSX_BUNDLE_LONG_VERSION_STRING\}/%s,\ %s/g > %s"%(VERSION,time.strftime("%Y-%b-%d"),targetinfo)
701     commands.getoutput(cmd)
702     cmd = 'cp %s/%s %s/%s.app/Contents/MacOS/%s'%(builddir, binary,installdir, binary, binary)
703     commands.getoutput(cmd)
704     cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/'%(installdir, binary, VERSION)
705     commands.getoutput(cmd)
706     cmd = installdir + '/%s.app/Contents/MacOS/%s'%(binary,VERSION)
707
708     # blenderplayer doesn't need all the files
709     if binary == 'blender':
710         cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/datafiles'%(installdir, binary, VERSION)
711         commands.getoutput(cmd)
712         cmd = 'cp -R %s/release/datafiles/fonts %s/%s.app/Contents/MacOS/%s/datafiles/'%(bldroot,installdir,binary,VERSION)
713         commands.getoutput(cmd)
714         mo_dir = os.path.join(builddir[:-4], "locale")
715         for f in os.listdir(mo_dir):
716             cmd = 'ditto %s/%s %s/%s.app/Contents/MacOS/%s/datafiles/locale/%s/LC_MESSAGES/blender.mo'%(mo_dir, f, installdir, binary, VERSION, f[:-3])
717             commands.getoutput(cmd)
718         cmd = 'cp %s/release/datafiles/locale/languages %s/%s.app/Contents/MacOS/%s/datafiles/locale/'%(bldroot, installdir, binary, VERSION)
719         commands.getoutput(cmd)
720
721         if env['WITH_BF_OCIO']:
722             cmd = 'cp -R %s/release/datafiles/colormanagement %s/%s.app/Contents/MacOS/%s/datafiles/'%(bldroot,installdir,binary,VERSION)
723             commands.getoutput(cmd)
724         
725         cmd = 'cp -R %s/release/scripts %s/%s.app/Contents/MacOS/%s/'%(bldroot,installdir,binary,VERSION)
726         commands.getoutput(cmd)
727
728         if VERSION_RELEASE_CYCLE == "release":
729             cmd = 'rm -rf %s/%s.app/Contents/MacOS/%s/scripts/addons_contrib'%(installdir,binary,VERSION)
730             commands.getoutput(cmd)
731
732         if env['WITH_BF_CYCLES']:
733             croot = '%s/intern/cycles' % (bldroot)
734             cinstalldir = '%s/%s.app/Contents/MacOS/%s/scripts/addons/cycles' % (installdir,binary,VERSION)
735
736             cmd = 'mkdir %s' % (cinstalldir)
737             commands.getoutput(cmd)
738             cmd = 'mkdir %s/kernel' % (cinstalldir)
739             commands.getoutput(cmd)
740             cmd = 'mkdir %s/lib' % (cinstalldir)
741             commands.getoutput(cmd)
742             cmd = 'cp -R %s/blender/addon/*.py %s/' % (croot, cinstalldir)
743             commands.getoutput(cmd)
744             cmd = 'cp -R %s/doc/license %s/license' % (croot, cinstalldir)
745             commands.getoutput(cmd)
746             cmd = 'cp -R %s/kernel/*.h %s/kernel/*.cl %s/kernel/*.cu %s/kernel/' % (croot, croot, croot, cinstalldir)
747             commands.getoutput(cmd)
748             cmd = 'cp -R %s/kernel/svm %s/kernel/closure %s/kernel/geom %s/util/util_color.h %s/util/util_half.h %s/util/util_math.h %s/util/util_transform.h %s/util/util_types.h %s/kernel/' % (croot, croot, croot, croot, croot, croot, croot, croot, cinstalldir)
749             commands.getoutput(cmd)
750             cmd = 'cp -R %s/../intern/cycles/kernel/*.cubin %s/lib/' % (builddir, cinstalldir)
751             commands.getoutput(cmd)
752
753             if env['WITH_BF_CYCLES_OSL']:
754                 cmd = 'mkdir %s/shader' % (cinstalldir)
755                 commands.getoutput(cmd)
756                 cmd = 'cp -R %s/kernel/shaders/*.h %s/shader' % (croot, cinstalldir)
757                 commands.getoutput(cmd)
758                 cmd = 'cp -R %s/../intern/cycles/kernel/shaders/*.oso %s/shader' % (builddir, cinstalldir)
759                 commands.getoutput(cmd)
760
761     if env['WITH_OSX_STATICPYTHON']:
762         cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/python/'%(installdir,binary, VERSION)
763         commands.getoutput(cmd)
764         cmd = 'unzip -q %s/release/%s -d %s/%s.app/Contents/MacOS/%s/python/'%(libdir,python_zip,installdir,binary,VERSION)
765         commands.getoutput(cmd)
766         cmd = 'cp -R %s/release/site-packages/ %s/%s.app/Contents/MacOS/%s/python/lib/python%s/site-packages/'%(libdir,installdir,binary,VERSION,env['BF_PYTHON_VERSION'])
767         commands.getoutput(cmd)
768
769     cmd = 'chmod +x  %s/%s.app/Contents/MacOS/%s'%(installdir,binary, binary)
770     commands.getoutput(cmd)
771     cmd = 'find %s/%s.app -name .svn -prune -exec rm -rf {} \;'%(installdir, binary)
772     commands.getoutput(cmd)
773     cmd = 'find %s/%s.app -name .DS_Store -exec rm -rf {} \;'%(installdir, binary)
774     commands.getoutput(cmd)
775     cmd = 'find %s/%s.app -name __MACOSX -exec rm -rf {} \;'%(installdir, binary)
776     commands.getoutput(cmd)
777     cmd = 'SetFile -d "%s)" -m "%s)" %s/%s.app'%(time.strftime("%m/%d/%Y %H:%M"),time.strftime("%m/%d/%Y %H:%M"),installdir,binary) # give the bundles actual creation/modification date
778     commands.getoutput(cmd)
779     if env['WITH_BF_OPENMP']:
780         if env['C_COMPILER_ID'] == 'gcc' and env['CCVERSION'] >= '4.6.1': # for correct errorhandling with gcc >= 4.6.1 we need the gcc.dylib and gomp.dylib to link, thus distribute in app-bundle
781             print "Bundling libgcc and libgomp"
782             instname = env['BF_CXX']
783             cmd = 'ditto --arch %s %s/lib/libgcc_s.1.dylib %s/%s.app/Contents/MacOS/lib/'%(osxarch, instname, installdir, binary) # copy libgcc
784             commands.getoutput(cmd)
785             cmd = 'install_name_tool -id @executable_path/lib/libgcc_s.1.dylib %s/%s.app/Contents/MacOS/lib/libgcc_s.1.dylib'%(installdir, binary) # change id of libgcc
786             commands.getoutput(cmd)
787             cmd = 'ditto --arch %s %s/lib/libgomp.1.dylib %s/%s.app/Contents/MacOS/lib/'%(osxarch, instname, installdir, binary) # copy libgomp
788             commands.getoutput(cmd)
789             cmd = 'install_name_tool -id @executable_path/lib/libgomp.1.dylib %s/%s.app/Contents/MacOS/lib/libgomp.1.dylib'%(installdir, binary) # change id of libgomp
790             commands.getoutput(cmd)
791             cmd = 'install_name_tool -change %s/lib/libgcc_s.1.dylib  @executable_path/lib/libgcc_s.1.dylib %s/%s.app/Contents/MacOS/lib/libgomp.1.dylib'%(instname, installdir, binary) # change ref to libgcc
792             commands.getoutput(cmd)
793             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) # change ref to libgcc ( blender )
794             commands.getoutput(cmd)
795             cmd = 'install_name_tool -change %s/lib/libgomp.1.dylib  @executable_path/lib/libgomp.1.dylib %s/%s.app/Contents/MacOS/%s'%(instname, installdir, binary, binary) # change ref to libgomp ( blender )
796             commands.getoutput(cmd)
797         if env['C_COMPILER_ID'] == 'clang' and env['CCVERSION'] >= '3.4':
798             print "Bundling libiomp5"
799             instname = env['LCGDIR'][1:] # made libiomp5 part of blender libs
800             cmd = 'ditto --arch %s %s/openmp/lib/libiomp5.dylib %s/%s.app/Contents/MacOS/lib/'%(osxarch, instname, installdir, binary) # copy libiomp5
801             commands.getoutput(cmd)
802             cmd = 'install_name_tool -id @loader_path/lib/libiomp5.dylib %s/%s.app/Contents/MacOS/lib/libiomp5.dylib'%(installdir, binary) # change id of libiomp5
803             commands.getoutput(cmd)
804             cmd = 'install_name_tool -change @loader_path/libiomp5.dylib  @loader_path/lib/libiomp5.dylib %s/%s.app/Contents/MacOS/%s'%(installdir, binary, binary) # change ref to libiomp5 ( blender )
805             commands.getoutput(cmd)
806
807 # extract copy system python, be sure to update other build systems
808 # when making changes to the files that are copied.
809 def my_unixpybundle_print(target, source, env):
810     pass
811
812 def UnixPyBundle(target=None, source=None, env=None):
813     # Any Unix except osx
814     #-- VERSION/python/lib/python3.1
815     
816     import commands
817     
818     def run(cmd):
819         print 'Install command:', cmd
820         commands.getoutput(cmd)
821
822     dir = os.path.join(env['BF_INSTALLDIR'], VERSION)
823
824     lib = env['BF_PYTHON_LIBPATH'].split(os.sep)[-1]
825     target_lib = "lib64" if lib == "lib64" else "lib"
826
827     py_src =    env.subst( env['BF_PYTHON_LIBPATH'] + '/python'+env['BF_PYTHON_VERSION'] )
828     py_target =    env.subst( dir + '/python/' + target_lib + '/python'+env['BF_PYTHON_VERSION'] )
829     
830     # This is a bit weak, but dont install if its been installed before, makes rebuilds quite slow.
831     if os.path.exists(py_target):
832         print 'Using existing python from:'
833         print '\t"%s"' %            py_target
834         print '\t(skipping copy)\n'
835         return
836
837     # Copied from source/creator/CMakeLists.txt, keep in sync.
838     print 'Install python from:'
839     print '\t"%s" into...' % py_src
840     print '\t"%s"\n' % py_target
841
842     run("rm -rf '%s'" % py_target)
843     try:
844         os.makedirs(os.path.dirname(py_target)) # the final part is copied
845     except:
846         pass
847
848     run("cp -R '%s' '%s'" % (py_src, os.path.dirname(py_target)))
849     run("rm -rf '%s/distutils'" % py_target)
850     run("rm -rf '%s/lib2to3'" % py_target)
851     run("rm -rf '%s/config'" % py_target)
852
853     for f in os.listdir(py_target):
854         if f.startswith("config-"):
855             run("rm -rf '%s/%s'" % (py_target, f))
856
857     run("rm -rf '%s/site-packages'" % py_target)
858     run("mkdir '%s/site-packages'" % py_target)    # python needs it.'
859     run("rm -rf '%s/idlelib'" % py_target)
860     run("rm -rf '%s/tkinter'" % py_target)
861     run("rm -rf '%s/turtledemo'" % py_target)
862     run("rm -r '%s/turtle.py'" % py_target)
863     run("rm -f '%s/lib-dynload/_tkinter.so'" % py_target)
864
865     if env['WITH_BF_PYTHON_INSTALL_NUMPY']:
866         numpy_src = py_src + "/site-packages/numpy"
867         numpy_target = py_target + "/site-packages/numpy"
868
869         if os.path.exists(numpy_src):
870             print 'Install numpy from:'
871             print '\t"%s" into...' % numpy_src
872             print '\t"%s"\n' % numpy_target
873
874             run("cp -R '%s' '%s'" % (numpy_src, os.path.dirname(numpy_target)))
875             run("rm -rf '%s/distutils'" % numpy_target)
876             run("rm -rf '%s/oldnumeric'" % numpy_target)
877             run("rm -rf '%s/doc'" % numpy_target)
878             run("rm -rf '%s/tests'" % numpy_target)
879             run("rm -rf '%s/f2py'" % numpy_target)
880             run("find '%s' -type d -name 'include' -prune -exec rm -rf {} ';'" % numpy_target)
881             run("find '%s' -type d -name '*.h' -prune -exec rm -rf {} ';'" % numpy_target)
882             run("find '%s' -type d -name '*.a' -prune -exec rm -rf {} ';'" % numpy_target)
883         else:
884             print 'Failed to find numpy at %s, skipping copying' % numpy_src
885         del numpy_src, numpy_target
886
887     if env['WITH_BF_PYTHON_INSTALL_REQUESTS']:
888         requests_src = py_src + "/site-packages/requests"
889         requests_target = py_target + "/site-packages/requests"
890         if os.path.exists(requests_src):
891             run("cp -R '%s' '%s'" % (requests_src, os.path.dirname(requests_target)))
892             run("find '%s' -type d -name '*.pem -prune -exec rm -rf {} ';'" % requests_target)
893         else:
894             print('Failed to find requests at %s, skipping copying' % requests_src)
895         del requests_src, requests_target
896
897     run("find '%s' -type d -name 'test' -prune -exec rm -rf {} ';'" % py_target)
898     run("find '%s' -type d -name '__pycache__' -exec rm -rf {} ';'" % py_target)
899     run("find '%s' -name '*.py[co]' -exec rm -rf {} ';'" % py_target)
900     run("find '%s' -name '*.so' -exec strip -s {} ';'" % py_target)
901
902 #### END ACTION STUFF #########
903
904 def bsc(env, target, source):
905     
906     bd = os.path.dirname(target[0].abspath)
907     bscfile = '\"'+target[0].abspath+'\"'
908     bscpathcollect = '\"'+bd + os.sep + '*.sbr\"'
909     bscpathtmp = '\"'+bd + os.sep + 'bscmake.tmp\"'
910
911     os.system('dir /b/s '+bscpathcollect+' >'+bscpathtmp)
912
913     myfile = open(bscpathtmp[1:-1], 'r')
914     lines = myfile.readlines()
915     myfile.close()
916
917     newfile = open(bscpathtmp[1:-1], 'w')
918     for l in lines:
919         newfile.write('\"'+l[:-1]+'\"\n')
920     newfile.close()
921                 
922     os.system('bscmake /nologo /n /o'+bscfile+' @'+bscpathtmp)
923     os.system('del '+bscpathtmp)
924
925 class BlenderEnvironment(SConsEnvironment):
926
927     PyBundleActionAdded = False
928
929     def BlenderRes(self=None, libname=None, source=None, libtype=['core'], priority=[100]):
930         global libs
931         if not self or not libname or not source:
932             print bc.FAIL+'Cannot continue.  Missing argument for BlenderRes '+libname+bc.ENDC
933             self.Exit()
934         if self['OURPLATFORM'] not in ('win32-vc','win32-mingw','linuxcross', 'win64-vc', 'win64-mingw'):
935             print bc.FAIL+'BlenderRes is for windows only!'+bc.END
936             self.Exit()
937         
938         print bc.HEADER+'Configuring resource '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC
939         lenv = self.Clone()
940         if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
941             res = lenv.RES('#'+root_build_dir+'lib/'+libname, source)
942         else:
943             res = lenv.RES(root_build_dir+'lib/'+libname, source)
944
945         
946         SConsEnvironment.Default(self, res)
947         resources.append(res)
948
949     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):
950         global vcp
951         
952         # sanity check
953         # run once in a while to check we dont have duplicates
954         if 0:
955             for name, dirs in (("source", sources), ("include", includes)):
956                 files_clean = [os.path.normpath(f) for f in dirs]
957                 files_clean_set = set(files_clean)
958                 if len(files_clean) != len(files_clean_set):
959                     for f in sorted(files_clean_set):
960                         if f != '.' and files_clean.count(f) > 1:
961                             raise Exception("Found duplicate %s %r" % (name, f))
962             del name, dirs, files_clean, files_clean_set, f
963         # end sanity check
964
965         if not self or not libname or not sources:
966             print bc.FAIL+'Cannot continue. Missing argument for BuildBlenderLib '+libname+bc.ENDC
967             self.Exit()
968
969         def list_substring(quickie, libname):
970             for q in quickie:
971                 if q in libname:
972                     return True
973             return False
974
975         if list_substring(quickie, libname) or len(quickie)==0:
976             if list_substring(quickdebug, libname):
977                 print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname +bc.ENDC+bc.OKBLUE+ " (debug mode)" + bc.ENDC
978             else:
979                 print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname + bc.ENDC
980             lenv = self.Clone()
981             lenv.Append(CPPPATH=includes)
982             lenv.Append(CPPDEFINES=defines)
983             if lenv['BF_DEBUG'] or (libname in quickdebug):
984                 lenv.Append(CFLAGS = lenv['BF_DEBUG_CFLAGS'])
985                 lenv.Append(CCFLAGS = lenv['BF_DEBUG_CCFLAGS'])
986                 lenv.Append(CXXFLAGS = lenv['BF_DEBUG_CXXFLAGS'])
987             else:
988                 lenv.Append(CFLAGS = lenv['REL_CFLAGS'])
989                 lenv.Append(CCFLAGS = lenv['REL_CCFLAGS'])
990                 lenv.Append(CXXFLAGS = lenv['REL_CXXFLAGS'])
991             if lenv['BF_PROFILE']:
992                 lenv.Append(CFLAGS = lenv['BF_PROFILE_CFLAGS'])
993                 lenv.Append(CCFLAGS = lenv['BF_PROFILE_CCFLAGS'])
994                 lenv.Append(CXXFLAGS = lenv['BF_PROFILE_CXXFLAGS'])
995             if compileflags:
996                 lenv.Replace(CFLAGS = compileflags)
997             if cc_compileflags:
998                 lenv.Replace(CCFLAGS = cc_compileflags)
999             if cxx_compileflags:
1000                 lenv.Replace(CXXFLAGS = cxx_compileflags)
1001             if cc_compilerchange:
1002                 lenv.Replace(CC = cc_compilerchange)
1003             if cxx_compilerchange:
1004                 lenv.Replace(CXX = cxx_compilerchange)
1005             lenv.Append(CFLAGS = lenv['C_WARN'])
1006             lenv.Append(CCFLAGS = lenv['CC_WARN'])
1007             lenv.Append(CXXFLAGS = lenv['CXX_WARN'])
1008
1009             if lenv['OURPLATFORM'] == 'win64-vc':
1010                 lenv.Append(LINKFLAGS = ['/MACHINE:X64'])
1011
1012             if lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
1013                 if lenv['BF_DEBUG']:
1014                     lenv.Append(CCFLAGS = ['/MTd'])
1015                 else:
1016                     lenv.Append(CCFLAGS = ['/MT'])
1017             
1018             targetdir = root_build_dir+'lib/' + libname
1019             if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
1020                 targetdir = '#'+targetdir
1021             lib = lenv.Library(target= targetdir, source=sources)
1022             SConsEnvironment.Default(self, lib) # we add to default target, because this way we get some kind of progress info during build
1023             if self['BF_MSVS'] and self['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
1024                 #if targetdir[0] == '#':
1025                 #    targetdir = targetdir[1:-1]
1026                 print "! ",targetdir+ '.vcproj' # + self['MSVSPROJECTSUFFIX']
1027                 vcproject = self.MSVSProject(target = targetdir + '.vcproj', # + self['MSVSPROJECTSUFFIX'],
1028                          srcs = sources,
1029                          buildtarget = lib,
1030                          variant = 'Release',
1031                          auto_build_solution=0)
1032                 vcp.append(vcproject)
1033                 SConsEnvironment.Default(self, vcproject)
1034         else:
1035             print bc.WARNING+'Not building '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC+' for '+bc.OKBLUE+'BF_QUICK'+bc.ENDC
1036         # note: libs is a global
1037         add_lib_to_dict(self, libs, libtype, libname, priority)
1038
1039     def BlenderProg(self=None, builddir=None, progname=None, sources=None, libs=None, libpath=None, binarykind=''):
1040         global vcp
1041         print bc.HEADER+'Configuring program '+bc.ENDC+bc.OKGREEN+progname+bc.ENDC
1042         lenv = self.Clone()
1043         lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
1044         lenv.Append(LINKFLAGS = lenv['BF_PROGRAM_LINKFLAGS'])
1045         if lenv['OURPLATFORM'] in ('win32-mingw', 'win64-mingw', 'linuxcross', 'cygwin', 'linux'):
1046             lenv.Replace(LINK = '$CXX')
1047         if lenv['OURPLATFORM'] in ('win32-vc', 'cygwin', 'win64-vc'):
1048             if lenv['BF_DEBUG']:
1049                 lenv.Prepend(LINKFLAGS = ['/DEBUG','/PDB:'+progname+'.pdb','/NODEFAULTLIB:libcmt'])
1050         if  lenv['OURPLATFORM']=='linux':
1051             if lenv['WITH_BF_PYTHON']:
1052                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
1053         if  lenv['OURPLATFORM']=='sunos5':
1054             if lenv['WITH_BF_PYTHON']:
1055                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
1056             if lenv['CXX'].endswith('CC'):
1057                 lenv.Replace(LINK = '$CXX')
1058         if  lenv['OURPLATFORM']=='darwin':
1059             if lenv['WITH_BF_PYTHON']:
1060                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
1061             lenv.Append(LINKFLAGS = lenv['BF_OPENGL_LINKFLAGS'])
1062         if lenv['BF_PROFILE']:
1063             lenv.Append(LINKFLAGS = lenv['BF_PROFILE_LINKFLAGS'])
1064         if root_build_dir[0]==os.sep or root_build_dir[1]==':':
1065             lenv.Append(LIBPATH=root_build_dir + '/lib')
1066         lenv.Append(LIBPATH=libpath)
1067         lenv.Append(LIBS=libs)
1068         if lenv['WITH_BF_QUICKTIME']:
1069             lenv.Append(LIBS = lenv['BF_QUICKTIME_LIB'])
1070             lenv.Append(LIBPATH = lenv['BF_QUICKTIME_LIBPATH'])
1071         prog = lenv.Program(target=builddir+'bin/'+progname, source=sources)
1072         if lenv['BF_DEBUG'] and lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc') and lenv['BF_BSC']:
1073             f = lenv.File(progname + '.bsc', builddir)
1074             brs = lenv.Command(f, prog, [bsc])
1075             SConsEnvironment.Default(self, brs)
1076         SConsEnvironment.Default(self, prog)
1077         if self['BF_MSVS'] and self['OURPLATFORM'] in ('win32-vc', 'win64-vc') and progname == 'blender':
1078             print "! ",builddir + "/" + progname + '.sln'
1079             sln = self.MSVSProject(target = builddir + "/" + progname + '.sln',
1080                      projects= vcp,
1081                      variant = 'Release')
1082             SConsEnvironment.Default(self, sln)
1083         program_list.append(prog)
1084         if  lenv['OURPLATFORM']=='darwin':
1085             lenv['BINARYKIND'] = binarykind
1086             lenv.AddPostAction(prog,Action(AppIt,strfunction=my_appit_print))
1087         elif os.sep == '/' and lenv['OURPLATFORM'] != 'linuxcross': # any unix (except cross-compilation)
1088             if lenv['WITH_BF_PYTHON']:
1089                 if (not lenv['WITHOUT_BF_INSTALL'] and 
1090                     not lenv['WITHOUT_BF_PYTHON_INSTALL'] and 
1091                     not lenv['WITHOUT_BF_PYTHON_UNPACK'] and 
1092                     not BlenderEnvironment.PyBundleActionAdded):
1093                     lenv.AddPostAction(prog,Action(UnixPyBundle,strfunction=my_unixpybundle_print))
1094                     BlenderEnvironment.PyBundleActionAdded = True
1095         elif lenv['OURPLATFORM'].startswith('win') or lenv['OURPLATFORM'] == 'linuxcross': # windows or cross-compilation
1096             if lenv['WITH_BF_PYTHON']:
1097                 if (not lenv['WITHOUT_BF_PYTHON_INSTALL'] and 
1098                     not lenv['WITHOUT_BF_PYTHON_UNPACK'] and 
1099                     not BlenderEnvironment.PyBundleActionAdded):
1100                     lenv.AddPostAction(prog,Action(WinPyBundle,strfunction=my_winpybundle_print))
1101                     BlenderEnvironment.PyBundleActionAdded = True
1102         return prog
1103
1104     def Glob(lenv, pattern):
1105         path = string.replace(GetBuildPath(lenv,'SConscript'),'SConscript', '')
1106         files = []
1107         for i in glob.glob(path + pattern):
1108             files.append(string.replace(i, path, ''))
1109         return files