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