Build system support for numpy on ms-windows
[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     # -------------
630     # Extract Numpy
631     py_tar = env.subst(env['LCGDIR'])
632     if py_tar[0] == '#':
633         py_tar = py_tar[1:]
634     py_tar += '/release/python' + env['BF_PYTHON_VERSION'].replace('.','') + '_numpy_1.8.tar.gz'
635
636     py_target = env.subst(env['BF_INSTALLDIR'])
637     if py_target[0] == '#':
638         py_target = py_target[1:]
639     py_target = os.path.join(py_target, VERSION, 'python', 'lib', 'site-packages')
640     # rmtree handled above
641     # files are cleaned up in their archive
642     exclude_re = []
643     print("Unpacking '" + py_tar + "' to '" + py_target + "'")
644     untar_pybundle(py_tar, py_target, exclude_re)
645
646
647 def  my_appit_print(target, source, env):
648     a = '%s' % (target[0])
649     d, f = os.path.split(a)
650     return "making bundle for " + f
651
652 def AppIt(target=None, source=None, env=None):
653     import shutil
654     import commands
655     import os.path
656     
657     
658     a = '%s' % (target[0])
659     builddir, b = os.path.split(a)
660     libdir = env['LCGDIR'][1:]
661     osxarch = env['MACOSX_ARCHITECTURE']
662     installdir = env['BF_INSTALLDIR']
663     print("compiled architecture: %s"%(osxarch))
664     print("Installing to %s"%(installdir))
665     # TODO, use tar.
666     python_zip = 'python_' + osxarch + '.zip' # set specific python_arch.zip
667     if env['WITH_OSX_STATICPYTHON']:
668         print("unzipping to app-bundle: %s"%(python_zip))
669     else:
670         print("dynamic build - make sure to have python3.x-framework installed")
671     bldroot = env.Dir('.').abspath
672     binary = env['BINARYKIND']
673      
674     sourcedir = bldroot + '/release/darwin/%s.app' % binary
675     sourceinfo = bldroot + "/release/darwin/%s.app/Contents/Info.plist"%binary
676     targetinfo = installdir +'/' + "%s.app/Contents/Info.plist"%binary
677     cmd = installdir + '/' +'%s.app'%binary
678     
679     if os.path.isdir(cmd):
680         shutil.rmtree(cmd)
681     shutil.copytree(sourcedir, cmd)
682     cmd = "cat %s | sed s/\$\{MACOSX_BUNDLE_SHORT_VERSION_STRING\}/%s/ | "%(sourceinfo,VERSION)
683     cmd += "sed s/\$\{MACOSX_BUNDLE_LONG_VERSION_STRING\}/%s,\ %s/g > %s"%(VERSION,time.strftime("%Y-%b-%d"),targetinfo)
684     commands.getoutput(cmd)
685     cmd = 'cp %s/%s %s/%s.app/Contents/MacOS/%s'%(builddir, binary,installdir, binary, binary)
686     commands.getoutput(cmd)
687     cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/'%(installdir, binary, VERSION)
688     commands.getoutput(cmd)
689     cmd = installdir + '/%s.app/Contents/MacOS/%s'%(binary,VERSION)
690
691     # blenderplayer doesn't need all the files
692     if binary == 'blender':
693         cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/datafiles'%(installdir, binary, VERSION)
694         commands.getoutput(cmd)
695         cmd = 'cp -R %s/release/datafiles/fonts %s/%s.app/Contents/MacOS/%s/datafiles/'%(bldroot,installdir,binary,VERSION)
696         commands.getoutput(cmd)
697         mo_dir = os.path.join(builddir[:-4], "locale")
698         for f in os.listdir(mo_dir):
699             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])
700             commands.getoutput(cmd)
701         cmd = 'cp %s/release/datafiles/locale/languages %s/%s.app/Contents/MacOS/%s/datafiles/locale/'%(bldroot, installdir, binary, VERSION)
702         commands.getoutput(cmd)
703
704         if env['WITH_BF_OCIO']:
705             cmd = 'cp -R %s/release/datafiles/colormanagement %s/%s.app/Contents/MacOS/%s/datafiles/'%(bldroot,installdir,binary,VERSION)
706             commands.getoutput(cmd)
707         
708         cmd = 'cp -R %s/release/scripts %s/%s.app/Contents/MacOS/%s/'%(bldroot,installdir,binary,VERSION)
709         commands.getoutput(cmd)
710
711         if VERSION_RELEASE_CYCLE == "release":
712             cmd = 'rm -rf %s/%s.app/Contents/MacOS/%s/scripts/addons_contrib'%(installdir,binary,VERSION)
713             commands.getoutput(cmd)
714
715         if env['WITH_BF_CYCLES']:
716             croot = '%s/intern/cycles' % (bldroot)
717             cinstalldir = '%s/%s.app/Contents/MacOS/%s/scripts/addons/cycles' % (installdir,binary,VERSION)
718
719             cmd = 'mkdir %s' % (cinstalldir)
720             commands.getoutput(cmd)
721             cmd = 'mkdir %s/kernel' % (cinstalldir)
722             commands.getoutput(cmd)
723             cmd = 'mkdir %s/lib' % (cinstalldir)
724             commands.getoutput(cmd)
725             cmd = 'cp -R %s/blender/addon/*.py %s/' % (croot, cinstalldir)
726             commands.getoutput(cmd)
727             cmd = 'cp -R %s/doc/license %s/license' % (croot, cinstalldir)
728             commands.getoutput(cmd)
729             cmd = 'cp -R %s/kernel/*.h %s/kernel/*.cl %s/kernel/*.cu %s/kernel/' % (croot, croot, croot, cinstalldir)
730             commands.getoutput(cmd)
731             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)
732             commands.getoutput(cmd)
733             cmd = 'cp -R %s/../intern/cycles/kernel/*.cubin %s/lib/' % (builddir, cinstalldir)
734             commands.getoutput(cmd)
735
736             if env['WITH_BF_CYCLES_OSL']:
737                 cmd = 'mkdir %s/shader' % (cinstalldir)
738                 commands.getoutput(cmd)
739                 cmd = 'cp -R %s/kernel/shaders/*.h %s/shader' % (croot, cinstalldir)
740                 commands.getoutput(cmd)
741                 cmd = 'cp -R %s/../intern/cycles/kernel/shaders/*.oso %s/shader' % (builddir, cinstalldir)
742                 commands.getoutput(cmd)
743
744     if env['WITH_OSX_STATICPYTHON']:
745         cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/python/'%(installdir,binary, VERSION)
746         commands.getoutput(cmd)
747         cmd = 'unzip -q %s/release/%s -d %s/%s.app/Contents/MacOS/%s/python/'%(libdir,python_zip,installdir,binary,VERSION)
748         commands.getoutput(cmd)
749
750     cmd = 'chmod +x  %s/%s.app/Contents/MacOS/%s'%(installdir,binary, binary)
751     commands.getoutput(cmd)
752     cmd = 'find %s/%s.app -name .svn -prune -exec rm -rf {} \;'%(installdir, binary)
753     commands.getoutput(cmd)
754     cmd = 'find %s/%s.app -name .DS_Store -exec rm -rf {} \;'%(installdir, binary)
755     commands.getoutput(cmd)
756     cmd = 'find %s/%s.app -name __MACOSX -exec rm -rf {} \;'%(installdir, binary)
757     commands.getoutput(cmd)
758     if env['WITH_BF_OPENMP']:
759         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
760             print "Bundling libgcc and libgomp"
761             instname = env['BF_CXX']
762             cmd = 'ditto --arch %s %s/lib/libgcc_s.1.dylib %s/%s.app/Contents/MacOS/lib/'%(osxarch, instname, installdir, binary) # copy libgcc
763             commands.getoutput(cmd)
764             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
765             commands.getoutput(cmd)
766             cmd = 'ditto --arch %s %s/lib/libgomp.1.dylib %s/%s.app/Contents/MacOS/lib/'%(osxarch, instname, installdir, binary) # copy libgomp
767             commands.getoutput(cmd)
768             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
769             commands.getoutput(cmd)
770             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
771             commands.getoutput(cmd)
772             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 )
773             commands.getoutput(cmd)
774             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 )
775             commands.getoutput(cmd)
776         if env['C_COMPILER_ID'] == 'clang' and env['CCVERSION'] >= '3.4':
777             print "Bundling libiomp5"
778             instname = env['LCGDIR'][1:] # made libiomp5 part of blender libs
779             cmd = 'ditto --arch %s %s/openmp/lib/libiomp5.dylib %s/%s.app/Contents/MacOS/lib/'%(osxarch, instname, installdir, binary) # copy libiomp5
780             commands.getoutput(cmd)
781             cmd = 'install_name_tool -id @loader_path/lib/libiomp5.dylib %s/%s.app/Contents/MacOS/lib/libiomp5.dylib'%(installdir, binary) # change id of libiomp5
782             commands.getoutput(cmd)
783             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 )
784             commands.getoutput(cmd)
785
786 # extract copy system python, be sure to update other build systems
787 # when making changes to the files that are copied.
788 def my_unixpybundle_print(target, source, env):
789     pass
790
791 def UnixPyBundle(target=None, source=None, env=None):
792     # Any Unix except osx
793     #-- VERSION/python/lib/python3.1
794     
795     import commands
796     
797     def run(cmd):
798         print 'Install command:', cmd
799         commands.getoutput(cmd)
800
801     dir = os.path.join(env['BF_INSTALLDIR'], VERSION)
802
803     lib = env['BF_PYTHON_LIBPATH'].split(os.sep)[-1]
804     target_lib = "lib64" if lib == "lib64" else "lib"
805
806     py_src =    env.subst( env['BF_PYTHON_LIBPATH'] + '/python'+env['BF_PYTHON_VERSION'] )
807     py_target =    env.subst( dir + '/python/' + target_lib + '/python'+env['BF_PYTHON_VERSION'] )
808     
809     # This is a bit weak, but dont install if its been installed before, makes rebuilds quite slow.
810     if os.path.exists(py_target):
811         print 'Using existing python from:'
812         print '\t"%s"' %            py_target
813         print '\t(skipping copy)\n'
814         return
815
816     # Copied from source/creator/CMakeLists.txt, keep in sync.
817     print 'Install python from:'
818     print '\t"%s" into...' % py_src
819     print '\t"%s"\n' % py_target
820
821     run("rm -rf '%s'" % py_target)
822     try:
823         os.makedirs(os.path.dirname(py_target)) # the final part is copied
824     except:
825         pass
826
827     run("cp -R '%s' '%s'" % (py_src, os.path.dirname(py_target)))
828     run("rm -rf '%s/distutils'" % py_target)
829     run("rm -rf '%s/lib2to3'" % py_target)
830     run("rm -rf '%s/config'" % py_target)
831
832     for f in os.listdir(py_target):
833         if f.startswith("config-"):
834             run("rm -rf '%s/%s'" % (py_target, f))
835
836     run("rm -rf '%s/site-packages'" % py_target)
837     run("mkdir '%s/site-packages'" % py_target)    # python needs it.'
838     run("rm -rf '%s/idlelib'" % py_target)
839     run("rm -rf '%s/tkinter'" % py_target)
840     run("rm -rf '%s/turtledemo'" % py_target)
841     run("rm -r '%s/turtle.py'" % py_target)
842     run("rm -f '%s/lib-dynload/_tkinter.so'" % py_target)
843
844     if env['WITH_BF_PYTHON_INSTALL_NUMPY']:
845         numpy_src = py_src + "/site-packages/numpy"
846         numpy_target = py_target + "/site-packages/numpy"
847
848         if os.path.exists(numpy_src):
849             print 'Install numpy from:'
850             print '\t"%s" into...' % numpy_src
851             print '\t"%s"\n' % numpy_target
852
853             run("cp -R '%s' '%s'" % (numpy_src, os.path.dirname(numpy_target)))
854             run("rm -rf '%s/distutils'" % numpy_target)
855             run("rm -rf '%s/oldnumeric'" % numpy_target)
856             run("rm -rf '%s/doc'" % numpy_target)
857             run("rm -rf '%s/tests'" % numpy_target)
858             run("rm -rf '%s/f2py'" % numpy_target)
859             run("find '%s' -type d -name 'include' -prune -exec rm -rf {} ';'" % numpy_target)
860             run("find '%s' -type d -name '*.h' -prune -exec rm -rf {} ';'" % numpy_target)
861             run("find '%s' -type d -name '*.a' -prune -exec rm -rf {} ';'" % numpy_target)
862         else:
863             print 'Failed to find numpy at %s, skipping copying' % numpy_src
864
865     run("find '%s' -type d -name 'test' -prune -exec rm -rf {} ';'" % py_target)
866     run("find '%s' -type d -name '__pycache__' -exec rm -rf {} ';'" % py_target)
867     run("find '%s' -name '*.py[co]' -exec rm -rf {} ';'" % py_target)
868     run("find '%s' -name '*.so' -exec strip -s {} ';'" % py_target)
869
870 #### END ACTION STUFF #########
871
872 def bsc(env, target, source):
873     
874     bd = os.path.dirname(target[0].abspath)
875     bscfile = '\"'+target[0].abspath+'\"'
876     bscpathcollect = '\"'+bd + os.sep + '*.sbr\"'
877     bscpathtmp = '\"'+bd + os.sep + 'bscmake.tmp\"'
878
879     os.system('dir /b/s '+bscpathcollect+' >'+bscpathtmp)
880
881     myfile = open(bscpathtmp[1:-1], 'r')
882     lines = myfile.readlines()
883     myfile.close()
884
885     newfile = open(bscpathtmp[1:-1], 'w')
886     for l in lines:
887         newfile.write('\"'+l[:-1]+'\"\n')
888     newfile.close()
889                 
890     os.system('bscmake /nologo /n /o'+bscfile+' @'+bscpathtmp)
891     os.system('del '+bscpathtmp)
892
893 class BlenderEnvironment(SConsEnvironment):
894
895     PyBundleActionAdded = False
896
897     def BlenderRes(self=None, libname=None, source=None, libtype=['core'], priority=[100]):
898         global libs
899         if not self or not libname or not source:
900             print bc.FAIL+'Cannot continue.  Missing argument for BlenderRes '+libname+bc.ENDC
901             self.Exit()
902         if self['OURPLATFORM'] not in ('win32-vc','win32-mingw','linuxcross', 'win64-vc', 'win64-mingw'):
903             print bc.FAIL+'BlenderRes is for windows only!'+bc.END
904             self.Exit()
905         
906         print bc.HEADER+'Configuring resource '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC
907         lenv = self.Clone()
908         if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
909             res = lenv.RES('#'+root_build_dir+'lib/'+libname, source)
910         else:
911             res = lenv.RES(root_build_dir+'lib/'+libname, source)
912
913         
914         SConsEnvironment.Default(self, res)
915         resources.append(res)
916
917     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):
918         global vcp
919         
920         # sanity check
921         # run once in a while to check we dont have duplicates
922         if 0:
923             for name, dirs in (("source", sources), ("include", includes)):
924                 files_clean = [os.path.normpath(f) for f in dirs]
925                 files_clean_set = set(files_clean)
926                 if len(files_clean) != len(files_clean_set):
927                     for f in sorted(files_clean_set):
928                         if f != '.' and files_clean.count(f) > 1:
929                             raise Exception("Found duplicate %s %r" % (name, f))
930             del name, dirs, files_clean, files_clean_set, f
931         # end sanity check
932
933         if not self or not libname or not sources:
934             print bc.FAIL+'Cannot continue. Missing argument for BuildBlenderLib '+libname+bc.ENDC
935             self.Exit()
936
937         def list_substring(quickie, libname):
938             for q in quickie:
939                 if q in libname:
940                     return True
941             return False
942
943         if list_substring(quickie, libname) or len(quickie)==0:
944             if list_substring(quickdebug, libname):
945                 print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname +bc.ENDC+bc.OKBLUE+ " (debug mode)" + bc.ENDC
946             else:
947                 print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname + bc.ENDC
948             lenv = self.Clone()
949             lenv.Append(CPPPATH=includes)
950             lenv.Append(CPPDEFINES=defines)
951             if lenv['BF_DEBUG'] or (libname in quickdebug):
952                 lenv.Append(CFLAGS = lenv['BF_DEBUG_CFLAGS'])
953                 lenv.Append(CCFLAGS = lenv['BF_DEBUG_CCFLAGS'])
954                 lenv.Append(CXXFLAGS = lenv['BF_DEBUG_CXXFLAGS'])
955             else:
956                 lenv.Append(CFLAGS = lenv['REL_CFLAGS'])
957                 lenv.Append(CCFLAGS = lenv['REL_CCFLAGS'])
958                 lenv.Append(CXXFLAGS = lenv['REL_CXXFLAGS'])
959             if lenv['BF_PROFILE']:
960                 lenv.Append(CFLAGS = lenv['BF_PROFILE_CFLAGS'])
961                 lenv.Append(CCFLAGS = lenv['BF_PROFILE_CCFLAGS'])
962                 lenv.Append(CXXFLAGS = lenv['BF_PROFILE_CXXFLAGS'])
963             if compileflags:
964                 lenv.Replace(CFLAGS = compileflags)
965             if cc_compileflags:
966                 lenv.Replace(CCFLAGS = cc_compileflags)
967             if cxx_compileflags:
968                 lenv.Replace(CXXFLAGS = cxx_compileflags)
969             if cc_compilerchange:
970                 lenv.Replace(CC = cc_compilerchange)
971             if cxx_compilerchange:
972                 lenv.Replace(CXX = cxx_compilerchange)
973             lenv.Append(CFLAGS = lenv['C_WARN'])
974             lenv.Append(CCFLAGS = lenv['CC_WARN'])
975             lenv.Append(CXXFLAGS = lenv['CXX_WARN'])
976
977             if lenv['OURPLATFORM'] == 'win64-vc':
978                 lenv.Append(LINKFLAGS = ['/MACHINE:X64'])
979
980             if lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
981                 if lenv['BF_DEBUG']:
982                     lenv.Append(CCFLAGS = ['/MTd'])
983                 else:
984                     lenv.Append(CCFLAGS = ['/MT'])
985             
986             targetdir = root_build_dir+'lib/' + libname
987             if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
988                 targetdir = '#'+targetdir
989             lib = lenv.Library(target= targetdir, source=sources)
990             SConsEnvironment.Default(self, lib) # we add to default target, because this way we get some kind of progress info during build
991             if self['BF_MSVS'] and self['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
992                 #if targetdir[0] == '#':
993                 #    targetdir = targetdir[1:-1]
994                 print "! ",targetdir+ '.vcproj' # + self['MSVSPROJECTSUFFIX']
995                 vcproject = self.MSVSProject(target = targetdir + '.vcproj', # + self['MSVSPROJECTSUFFIX'],
996                          srcs = sources,
997                          buildtarget = lib,
998                          variant = 'Release',
999                          auto_build_solution=0)
1000                 vcp.append(vcproject)
1001                 SConsEnvironment.Default(self, vcproject)
1002         else:
1003             print bc.WARNING+'Not building '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC+' for '+bc.OKBLUE+'BF_QUICK'+bc.ENDC
1004         # note: libs is a global
1005         add_lib_to_dict(self, libs, libtype, libname, priority)
1006
1007     def BlenderProg(self=None, builddir=None, progname=None, sources=None, libs=None, libpath=None, binarykind=''):
1008         global vcp
1009         print bc.HEADER+'Configuring program '+bc.ENDC+bc.OKGREEN+progname+bc.ENDC
1010         lenv = self.Clone()
1011         lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
1012         lenv.Append(LINKFLAGS = lenv['BF_PROGRAM_LINKFLAGS'])
1013         if lenv['OURPLATFORM'] in ('win32-mingw', 'win64-mingw', 'linuxcross', 'cygwin', 'linux'):
1014             lenv.Replace(LINK = '$CXX')
1015         if lenv['OURPLATFORM'] in ('win32-vc', 'cygwin', 'win64-vc'):
1016             if lenv['BF_DEBUG']:
1017                 lenv.Prepend(LINKFLAGS = ['/DEBUG','/PDB:'+progname+'.pdb','/NODEFAULTLIB:libcmt'])
1018         if  lenv['OURPLATFORM']=='linux':
1019             if lenv['WITH_BF_PYTHON']:
1020                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
1021         if  lenv['OURPLATFORM']=='sunos5':
1022             if lenv['WITH_BF_PYTHON']:
1023                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
1024             if lenv['CXX'].endswith('CC'):
1025                 lenv.Replace(LINK = '$CXX')
1026         if  lenv['OURPLATFORM']=='darwin':
1027             if lenv['WITH_BF_PYTHON']:
1028                 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
1029             lenv.Append(LINKFLAGS = lenv['BF_OPENGL_LINKFLAGS'])
1030         if lenv['BF_PROFILE']:
1031             lenv.Append(LINKFLAGS = lenv['BF_PROFILE_LINKFLAGS'])
1032         if root_build_dir[0]==os.sep or root_build_dir[1]==':':
1033             lenv.Append(LIBPATH=root_build_dir + '/lib')
1034         lenv.Append(LIBPATH=libpath)
1035         lenv.Append(LIBS=libs)
1036         if lenv['WITH_BF_QUICKTIME']:
1037             lenv.Append(LIBS = lenv['BF_QUICKTIME_LIB'])
1038             lenv.Append(LIBPATH = lenv['BF_QUICKTIME_LIBPATH'])
1039         prog = lenv.Program(target=builddir+'bin/'+progname, source=sources)
1040         if lenv['BF_DEBUG'] and lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc') and lenv['BF_BSC']:
1041             f = lenv.File(progname + '.bsc', builddir)
1042             brs = lenv.Command(f, prog, [bsc])
1043             SConsEnvironment.Default(self, brs)
1044         SConsEnvironment.Default(self, prog)
1045         if self['BF_MSVS'] and self['OURPLATFORM'] in ('win32-vc', 'win64-vc') and progname == 'blender':
1046             print "! ",builddir + "/" + progname + '.sln'
1047             sln = self.MSVSProject(target = builddir + "/" + progname + '.sln',
1048                      projects= vcp,
1049                      variant = 'Release')
1050             SConsEnvironment.Default(self, sln)
1051         program_list.append(prog)
1052         if  lenv['OURPLATFORM']=='darwin':
1053             lenv['BINARYKIND'] = binarykind
1054             lenv.AddPostAction(prog,Action(AppIt,strfunction=my_appit_print))
1055         elif os.sep == '/' and lenv['OURPLATFORM'] != 'linuxcross': # any unix (except cross-compilation)
1056             if lenv['WITH_BF_PYTHON']:
1057                 if (not lenv['WITHOUT_BF_INSTALL'] and 
1058                     not lenv['WITHOUT_BF_PYTHON_INSTALL'] and 
1059                     not lenv['WITHOUT_BF_PYTHON_UNPACK'] and 
1060                     not BlenderEnvironment.PyBundleActionAdded):
1061                     lenv.AddPostAction(prog,Action(UnixPyBundle,strfunction=my_unixpybundle_print))
1062                     BlenderEnvironment.PyBundleActionAdded = True
1063         elif lenv['OURPLATFORM'].startswith('win') or lenv['OURPLATFORM'] == 'linuxcross': # windows or cross-compilation
1064             if lenv['WITH_BF_PYTHON']:
1065                 if (not lenv['WITHOUT_BF_PYTHON_INSTALL'] and 
1066                     not lenv['WITHOUT_BF_PYTHON_UNPACK'] and 
1067                     not BlenderEnvironment.PyBundleActionAdded):
1068                     lenv.AddPostAction(prog,Action(WinPyBundle,strfunction=my_winpybundle_print))
1069                     BlenderEnvironment.PyBundleActionAdded = True
1070         return prog
1071
1072     def Glob(lenv, pattern):
1073         path = string.replace(GetBuildPath(lenv,'SConscript'),'SConscript', '')
1074         files = []
1075         for i in glob.glob(path + pattern):
1076             files.append(string.replace(i, path, ''))
1077         return files