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