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