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