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