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