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