4 tools.BlenderEnvironment
6 This environment builds on SCons.Script.SConscript.SConsEnvironment
12 TODO: clean up and sanitise code - crosscheck with btools and SConstruct
13 to kill any code duplication
28 from SCons.Script.SConscript import SConsEnvironment
34 bc = bcolors.bcolors()
36 VERSION = btools.VERSION
37 VERSION_RELEASE_CYCLE = btools.VERSION_RELEASE_CYCLE
39 Split = SCons.Util.Split
40 Action = SCons.Action.Action
41 Builder = SCons.Builder.Builder
42 GetBuildPath = SConsEnvironment.GetBuildPath
47 quickie = None # Anything else than None if BF_QUICK has been passed
48 quicklist = [] # The list of libraries/programs to compile during a quickie
49 program_list = [] # A list holding Nodes to final binaries, used to create installs
56 blenderdeps = [] # don't manipulate this one outside this module!
58 ##### LIB STUFF ##########
60 possible_types = ['core'] # can be set in ie. SConstruct
68 for pt in possible_types:
71 # helper func for add_lib_to_dict
72 def internal_lib_to_dict(dict = None, libtype = None, libname = None, priority = 100):
73 if not libname in dict[libtype]:
76 if dict[libtype].has_key(priority):
77 priority = priority + 1
80 dict[libtype][priority] = libname
82 # libtype and priority can both be lists, for defining lib in multiple places
83 def add_lib_to_dict(env, dict = None, libtype = None, libname = None, priority = 100):
84 if not dict or not libtype or not libname:
85 print "Passed wrong arg"
88 if type(libtype) is str and type(priority) is int:
89 internal_lib_to_dict(dict, libtype, libname, priority)
90 elif type(libtype) is list and type(priority) is list:
91 if len(libtype)==len(priority):
92 for lt, p in zip(libtype, priority):
93 internal_lib_to_dict(dict, lt, libname, p)
95 print "libtype and priority lists are unequal in length"
98 print "Wrong type combinations for libtype and priority. Only str and int or list and list"
101 def create_blender_liblist(lenv = None, libtype = None):
102 if not lenv or not libtype:
106 if libtype in possible_types:
107 curlib = libs[libtype]
108 sortlist = curlib.keys()
112 if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
113 target = os.path.abspath(os.getcwd() + os.sep + root_build_dir + 'lib' + os.sep +lenv['LIBPREFIX'] + v + lenv['LIBSUFFIX'])
115 target = os.path.abspath(root_build_dir + 'lib' + os.sep +lenv['LIBPREFIX'] + v + lenv['LIBSUFFIX'])
120 ## TODO: static linking
121 def setup_staticlibs(lenv):
123 #here libs for static linking
128 if lenv['WITH_BF_FFMPEG']:
129 libincs += Split(lenv['BF_FFMPEG_LIBPATH'])
132 lenv['BF_OPENGL_LIBPATH'],
133 lenv['BF_JPEG_LIBPATH'],
134 lenv['BF_ZLIB_LIBPATH'],
135 lenv['BF_PNG_LIBPATH'],
136 lenv['BF_ICONV_LIBPATH']
139 if lenv['WITH_BF_STATICJPEG']:
140 statlibs += Split(lenv['BF_JPEG_LIB_STATIC'])
141 if lenv['WITH_BF_STATICPNG']:
142 statlibs += Split(lenv['BF_PNG_LIB_STATIC'])
144 libincs += Split(lenv['BF_FREETYPE_LIBPATH'])
145 if lenv['WITH_BF_PYTHON']:
146 libincs += Split(lenv['BF_PYTHON_LIBPATH'])
147 if lenv['WITH_BF_SDL']:
148 libincs += Split(lenv['BF_SDL_LIBPATH'])
149 if lenv['WITH_BF_JACK']:
150 libincs += Split(lenv['BF_JACK_LIBPATH'])
151 if lenv['WITH_BF_STATICJACK']:
152 statlibs += Split(lenv['BF_JACK_LIB_STATIC'])
153 if lenv['WITH_BF_SNDFILE']:
154 libincs += Split(lenv['BF_SNDFILE_LIBPATH'])
155 if lenv['WITH_BF_OPENEXR']:
156 libincs += Split(lenv['BF_OPENEXR_LIBPATH'])
157 if lenv['WITH_BF_STATICOPENEXR']:
158 statlibs += Split(lenv['BF_OPENEXR_LIB_STATIC'])
159 if lenv['WITH_BF_TIFF']:
160 libincs += Split(lenv['BF_TIFF_LIBPATH'])
161 if lenv['WITH_BF_STATICTIFF']:
162 statlibs += Split(lenv['BF_TIFF_LIB_STATIC'])
163 if lenv['WITH_BF_ZLIB'] and lenv['WITH_BF_STATICZLIB']:
164 statlibs += Split(lenv['BF_ZLIB_LIB_STATIC'])
165 if lenv['WITH_BF_FFTW3']:
166 libincs += Split(lenv['BF_FFTW3_LIBPATH'])
167 if lenv['WITH_BF_STATICFFTW3']:
168 statlibs += Split(lenv['BF_FFTW3_LIB_STATIC'])
169 if lenv['WITH_BF_ELTOPO']:
170 libincs += Split(lenv['BF_LAPACK_LIBPATH'])
171 if lenv['WITH_BF_STATICLAPACK']:
172 statlibs += Split(lenv['BF_LAPACK_LIB_STATIC'])
173 if lenv['WITH_BF_FFMPEG'] and lenv['WITH_BF_STATICFFMPEG']:
174 statlibs += Split(lenv['BF_FFMPEG_LIB_STATIC'])
175 if lenv['WITH_BF_INTERNATIONAL']:
176 if lenv['WITH_BF_FREETYPE_STATIC']:
177 statlibs += Split(lenv['BF_FREETYPE_LIB_STATIC'])
178 if lenv['WITH_BF_OPENAL']:
179 libincs += Split(lenv['BF_OPENAL_LIBPATH'])
180 if lenv['WITH_BF_STATICOPENAL']:
181 statlibs += Split(lenv['BF_OPENAL_LIB_STATIC'])
182 if lenv['WITH_BF_STATICOPENGL']:
183 statlibs += Split(lenv['BF_OPENGL_LIB_STATIC'])
184 if lenv['WITH_BF_STATICCXX']:
185 statlibs += Split(lenv['BF_CXX_LIB_STATIC'])
187 if lenv['WITH_BF_PYTHON'] and lenv['WITH_BF_STATICPYTHON']:
188 statlibs += Split(lenv['BF_PYTHON_LIB_STATIC'])
190 if lenv['WITH_BF_SNDFILE'] and lenv['WITH_BF_STATICSNDFILE']:
191 statlibs += Split(lenv['BF_SNDFILE_LIB_STATIC'])
193 if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
194 libincs += Split(lenv['BF_PTHREADS_LIBPATH'])
196 if lenv['WITH_BF_COLLADA']:
197 libincs += Split(lenv['BF_OPENCOLLADA_LIBPATH'])
198 if lenv['OURPLATFORM'] not in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
199 libincs += Split(lenv['BF_PCRE_LIBPATH'])
200 libincs += Split(lenv['BF_EXPAT_LIBPATH'])
201 if lenv['WITH_BF_STATICOPENCOLLADA']:
202 statlibs += Split(lenv['BF_OPENCOLLADA_LIB_STATIC'])
204 if lenv['WITH_BF_OPENMP']:
205 if lenv['OURPLATFORM'] == 'linuxcross':
206 libincs += Split(lenv['BF_OPENMP_LIBPATH'])
207 if lenv['WITH_BF_STATICOPENMP']:
208 statlibs += Split(lenv['BF_OPENMP_LIB_STATIC'])
210 if lenv['WITH_BF_OIIO']:
211 libincs += Split(lenv['BF_OIIO_LIBPATH'])
212 if lenv['WITH_BF_STATICOIIO']:
213 statlibs += Split(lenv['BF_OIIO_LIB_STATIC'])
215 if lenv['WITH_BF_OCIO']:
216 libincs += Split(lenv['BF_OCIO_LIBPATH'])
217 if lenv['WITH_BF_STATICOCIO']:
218 statlibs += Split(lenv['BF_OCIO_LIB_STATIC'])
220 if lenv['WITH_BF_BOOST']:
221 libincs += Split(lenv['BF_BOOST_LIBPATH'])
222 if lenv['WITH_BF_STATICBOOST']:
223 statlibs += Split(lenv['BF_BOOST_LIB_STATIC'])
225 # setting this last so any overriding of manually libs could be handled
226 if lenv['OURPLATFORM'] not in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross', 'win64-mingw'):
227 libincs.append('/usr/lib')
229 if lenv['WITH_BF_JEMALLOC']:
230 libincs += Split(lenv['BF_JEMALLOC_LIBPATH'])
231 if lenv['WITH_BF_STATICJEMALLOC']:
232 statlibs += Split(lenv['BF_JEMALLOC_LIB_STATIC'])
234 if lenv['OURPLATFORM']=='linux':
235 if lenv['WITH_BF_3DMOUSE']:
236 libincs += Split(lenv['BF_3DMOUSE_LIBPATH'])
237 if lenv['WITH_BF_STATIC3DMOUSE']:
238 statlibs += Split(lenv['BF_3DMOUSE_LIB_STATIC'])
240 return statlibs, libincs
242 def setup_syslibs(lenv):
245 if not lenv['WITH_BF_FREETYPE_STATIC']:
246 syslibs += Split(lenv['BF_FREETYPE_LIB'])
247 if lenv['WITH_BF_PYTHON'] and not lenv['WITH_BF_STATICPYTHON']:
248 if lenv['BF_DEBUG'] and lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc', 'win32-mingw', 'win64-mingw'):
249 syslibs.append(lenv['BF_PYTHON_LIB']+'_d')
251 syslibs.append(lenv['BF_PYTHON_LIB'])
252 if lenv['WITH_BF_OPENAL']:
253 if not lenv['WITH_BF_STATICOPENAL']:
254 syslibs += Split(lenv['BF_OPENAL_LIB'])
255 if lenv['WITH_BF_OPENMP'] and lenv['CC'] != 'icc' and not lenv['WITH_BF_STATICOPENMP']:
256 if lenv['CC'] == 'cl.exe':
260 if lenv['WITH_BF_ICONV']:
261 syslibs += Split(lenv['BF_ICONV_LIB'])
262 if lenv['WITH_BF_OIIO']:
263 if not lenv['WITH_BF_STATICOIIO']:
264 syslibs += Split(lenv['BF_OIIO_LIB'])
266 if lenv['WITH_BF_OCIO']:
267 if not lenv['WITH_BF_STATICOCIO']:
268 syslibs += Split(lenv['BF_OCIO_LIB'])
270 if lenv['WITH_BF_OPENEXR'] and not lenv['WITH_BF_STATICOPENEXR']:
271 syslibs += Split(lenv['BF_OPENEXR_LIB'])
272 if lenv['WITH_BF_TIFF'] and not lenv['WITH_BF_STATICTIFF']:
273 syslibs += Split(lenv['BF_TIFF_LIB'])
274 if lenv['WITH_BF_ZLIB'] and not lenv['WITH_BF_STATICZLIB']:
275 syslibs += Split(lenv['BF_ZLIB_LIB'])
276 if lenv['WITH_BF_FFMPEG'] and not lenv['WITH_BF_STATICFFMPEG']:
277 syslibs += Split(lenv['BF_FFMPEG_LIB'])
278 if lenv['WITH_BF_OGG']:
279 syslibs += Split(lenv['BF_OGG_LIB'])
280 if lenv['WITH_BF_JACK'] and not lenv['WITH_BF_STATICJACK']:
281 syslibs += Split(lenv['BF_JACK_LIB'])
282 if lenv['WITH_BF_SNDFILE'] and not lenv['WITH_BF_STATICSNDFILE']:
283 syslibs += Split(lenv['BF_SNDFILE_LIB'])
284 if lenv['WITH_BF_FFTW3'] and not lenv['WITH_BF_STATICFFTW3']:
285 syslibs += Split(lenv['BF_FFTW3_LIB'])
286 if lenv['WITH_BF_ELTOPO']:
287 syslibs += Split(lenv['BF_LAPACK_LIB'])
288 if lenv['WITH_BF_SDL']:
289 syslibs += Split(lenv['BF_SDL_LIB'])
290 if not lenv['WITH_BF_STATICOPENGL']:
291 syslibs += Split(lenv['BF_OPENGL_LIB'])
292 if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw','linuxcross', 'win64-vc', 'win64-mingw'):
293 syslibs += Split(lenv['BF_PTHREADS_LIB'])
294 if lenv['WITH_BF_COLLADA'] and not lenv['WITH_BF_STATICOPENCOLLADA']:
295 syslibs.append(lenv['BF_PCRE_LIB'])
296 if lenv['BF_DEBUG'] and (lenv['OURPLATFORM'] != 'linux'):
297 syslibs += [colladalib+'_d' for colladalib in Split(lenv['BF_OPENCOLLADA_LIB'])]
299 syslibs += Split(lenv['BF_OPENCOLLADA_LIB'])
300 syslibs.append(lenv['BF_EXPAT_LIB'])
302 if lenv['WITH_BF_JEMALLOC']:
303 if not lenv['WITH_BF_STATICJEMALLOC']:
304 syslibs += Split(lenv['BF_JEMALLOC_LIB'])
306 if lenv['OURPLATFORM']=='linux':
307 if lenv['WITH_BF_3DMOUSE']:
308 if not lenv['WITH_BF_STATIC3DMOUSE']:
309 syslibs += Split(lenv['BF_3DMOUSE_LIB'])
311 if lenv['WITH_BF_BOOST'] and not lenv['WITH_BF_STATICBOOST']:
312 syslibs += Split(lenv['BF_BOOST_LIB'])
314 if lenv['WITH_BF_INTERNATIONAL']:
315 syslibs += Split(lenv['BF_BOOST_LIB_INTERNATIONAL'])
317 if not lenv['WITH_BF_STATICJPEG']:
318 syslibs += Split(lenv['BF_JPEG_LIB'])
320 if not lenv['WITH_BF_STATICPNG']:
321 syslibs += Split(lenv['BF_PNG_LIB'])
323 syslibs += lenv['LLIBS']
327 def propose_priorities():
328 print bc.OKBLUE+"Priorities:"+bc.ENDC
329 for t in possible_types:
330 print bc.OKGREEN+"\t"+t+bc.ENDC
333 sortlist = curlib.keys()
338 #for p,v in sorted(libs[t].iteritems()):
339 print "\t\t",new_priority, v
342 # emits the necessary file objects for creator.c, to be used in creating
343 # the final blender executable
345 sources = ['creator.c']# + Blender.buildinfo(env, "dynamic") + Blender.resources
347 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', '#/source/blender/freestyle', env['BF_OPENGL_INC']]
351 if env['WITH_BF_BINRELOC']:
352 incs.append('#/extern/binreloc/include')
353 defs.append('WITH_BINRELOC')
355 if env['WITH_BF_SDL']:
356 defs.append('WITH_SDL')
358 if env['WITH_BF_LIBMV']:
359 incs.append('#/extern/libmv')
360 defs.append('WITH_LIBMV')
362 if env['WITH_BF_FFMPEG']:
363 defs.append('WITH_FFMPEG')
365 if env['WITH_BF_PYTHON']:
366 incs.append('#/source/blender/python')
367 defs.append('WITH_PYTHON')
369 defs.append('_DEBUG')
371 if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
372 incs.append(env['BF_PTHREADS_INC'])
373 incs.append('#/intern/utfconv')
375 env.Append(CPPDEFINES=defs)
376 env.Append(CPPPATH=incs)
377 obj = [env.Object(root_build_dir+'source/creator/creator/creator', ['#source/creator/creator.c'])]
381 ## TODO: see if this can be made in an emitter
382 def buildinfo(lenv, build_type):
384 Generate a buildinfo object
386 build_date = time.strftime ("%Y-%m-%d")
387 build_time = time.strftime ("%H:%M:%S")
388 build_rev = os.popen('svnversion').read()[:-1] # remove \n
390 build_rev = '-UNKNOWN-'
393 build_cflags = ' '.join(lenv['CFLAGS'] + lenv['CCFLAGS'] + lenv['BF_DEBUG_CCFLAGS'] + lenv['CPPFLAGS'])
394 build_cxxflags = ' '.join(lenv['CCFLAGS'] + lenv['CXXFLAGS'] + lenv['CPPFLAGS'])
396 build_type = "Release"
397 build_cflags = ' '.join(lenv['CFLAGS'] + lenv['CCFLAGS'] + lenv['REL_CFLAGS'] + lenv['REL_CCFLAGS'] + lenv['CPPFLAGS'])
398 build_cxxflags = ' '.join(lenv['CCFLAGS'] + lenv['CXXFLAGS'] + lenv['REL_CXXFLAGS'] + lenv['REL_CCFLAGS'] + lenv['CPPFLAGS'])
400 build_linkflags = ' '.join(lenv['PLATFORM_LINKFLAGS'])
403 if lenv['BF_BUILDINFO']:
404 lenv.Append (CPPDEFINES = ['BUILD_TIME=\\"%s\\"'%(build_time),
405 'BUILD_DATE=\\"%s\\"'%(build_date),
406 'BUILD_TYPE=\\"%s\\"'%(build_type),
407 'BUILD_REV=\\"%s\\"'%(build_rev),
409 'BUILD_PLATFORM=\\"%s:%s\\"'%(platform.system(), platform.architecture()[0]),
410 'BUILD_CFLAGS=\\"%s\\"'%(build_cflags),
411 'BUILD_CXXFLAGS=\\"%s\\"'%(build_cxxflags),
412 'BUILD_LINKFLAGS=\\"%s\\"'%(build_linkflags),
413 'BUILD_SYSTEM=\\"SCons\\"'
416 lenv.Append (CPPPATH = [root_build_dir+'source/blender/blenkernel'])
418 obj = [lenv.Object (root_build_dir+'source/creator/%s_buildinfo'%build_type, ['#source/creator/buildinfo.c'])]
422 ##### END LIB STUFF ############
424 ##### ACTION STUFF #############
426 def my_print_cmd_line(self, s, target, source, env):
427 sys.stdout.write(' ' * 70 + '\r')
429 sys.stdout.write(s + "\r")
432 def my_compile_print(target, source, env):
433 a = '%s' % (source[0])
434 d, f = os.path.split(a)
435 return bc.OKBLUE+"Compiling"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
437 def my_moc_print(target, source, env):
438 a = '%s' % (source[0])
439 d, f = os.path.split(a)
440 return bc.OKBLUE+"Creating MOC"+bc.ENDC+ " ==> '"+bc.OKGREEN+"%s" %(f) + "'"+bc.ENDC
442 def my_linking_print(target, source, env):
443 t = '%s' % (target[0])
444 d, f = os.path.split(t)
445 return bc.OKBLUE+"Linking library"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
447 def my_program_print(target, source, env):
448 t = '%s' % (target[0])
449 d, f = os.path.split(t)
450 return bc.OKBLUE+"Linking program"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
453 static_lib = SCons.Tool.createStaticLibBuilder(env)
454 program = SCons.Tool.createProgBuilder(env)
456 env['BUILDERS']['Library'] = static_lib
457 env['BUILDERS']['StaticLibrary'] = static_lib
458 env['BUILDERS']['Program'] = program
460 def set_quiet_output(env):
461 mycaction = Action("$CCCOM", strfunction=my_compile_print)
462 myshcaction = Action("$SHCCCOM", strfunction=my_compile_print)
463 mycppaction = Action("$CXXCOM", strfunction=my_compile_print)
464 myshcppaction = Action("$SHCXXCOM", strfunction=my_compile_print)
465 mylibaction = Action("$ARCOM", strfunction=my_linking_print)
466 mylinkaction = Action("$LINKCOM", strfunction=my_program_print)
468 static_ob, shared_ob = SCons.Tool.createObjBuilders(env)
469 static_ob.add_action('.c', mycaction)
470 static_ob.add_action('.cpp', mycppaction)
471 static_ob.add_action('.cc', mycppaction)
472 shared_ob.add_action('.c', myshcaction)
473 shared_ob.add_action('.cc', myshcppaction)
475 static_lib = SCons.Builder.Builder(action = mylibaction,
476 emitter = '$LIBEMITTER',
477 prefix = '$LIBPREFIX',
478 suffix = '$LIBSUFFIX',
479 src_suffix = '$OBJSUFFIX',
480 src_builder = 'StaticObject')
482 program = SCons.Builder.Builder(action = mylinkaction,
483 emitter = '$PROGEMITTER',
484 prefix = '$PROGPREFIX',
485 suffix = '$PROGSUFFIX',
486 src_suffix = '$OBJSUFFIX',
487 src_builder = 'Object',
488 target_scanner = SCons.Defaults.ProgScan)
490 env['BUILDERS']['Object'] = static_ob
491 env['BUILDERS']['StaticObject'] = static_ob
492 env['BUILDERS']['StaticLibrary'] = static_lib
493 env['BUILDERS']['Library'] = static_lib
494 env['BUILDERS']['Program'] = program
495 if env['BF_LINE_OVERWRITE']:
496 SCons.Action._ActionAction.print_cmd_line = my_print_cmd_line
498 def untar_pybundle(from_tar,to_dir,exclude_re):
499 tar= tarfile.open(from_tar, mode='r')
500 exclude_re= list(exclude_re) #single re object or list of re objects
501 debug= 0 #list files instead of unpacking
503 if debug: print '\nFiles not being unpacked:\n'
504 for name in tar.getnames():
512 good.append(tar.getmember(name))
514 print '\nFiles being unpacked:\n'
518 tar.extractall(to_dir, good)
520 def my_winpybundle_print(target, source, env):
523 def WinPyBundle(target=None, source=None, env=None):
525 py_tar= env.subst( env['LCGDIR'] )
529 py_tar+= '/release/python' + env['BF_PYTHON_VERSION'].replace('.','') + '_d.tar.gz'
531 py_tar+= '/release/python' + env['BF_PYTHON_VERSION'].replace('.','') + '.tar.gz'
533 py_target = env.subst( env['BF_INSTALLDIR'] )
534 if py_target[0]=='#':
535 py_target=py_target[1:]
536 py_target = os.path.join(py_target, VERSION, 'python', 'lib')
537 def printexception(func,path,ex):
538 if os.path.exists(path): #do not report if path does not exist. eg on a fresh build.
539 print str(func) + ' failed on ' + str(path)
540 print "Trying to remove existing py bundle."
541 shutil.rmtree(py_target, False, printexception)
542 exclude_re=[re.compile('.*/test'),
544 re.compile('^distutils'),
545 re.compile('^idlelib'),
546 re.compile('^lib2to3'),
547 re.compile('^tkinter'),
548 re.compile('^_tkinter_d.pyd'),
549 re.compile('^turtledemo'),
550 re.compile('^turtle.py'),
553 print "Unpacking '" + py_tar + "' to '" + py_target + "'"
554 untar_pybundle(py_tar,py_target,exclude_re)
556 def my_appit_print(target, source, env):
557 a = '%s' % (target[0])
558 d, f = os.path.split(a)
559 return "making bundle for " + f
561 def AppIt(target=None, source=None, env=None):
567 a = '%s' % (target[0])
568 builddir, b = os.path.split(a)
569 libdir = env['LCGDIR'][1:]
570 osxarch = env['MACOSX_ARCHITECTURE']
571 installdir = env['BF_INSTALLDIR']
572 print("compiled architecture: %s"%(osxarch))
573 print("Installing to %s"%(installdir))
575 python_zip = 'python_' + osxarch + '.zip' # set specific python_arch.zip
576 if env['WITH_OSX_STATICPYTHON']:
577 print("unzipping to app-bundle: %s"%(python_zip))
579 print("dynamic build - make sure to have python3.x-framework installed")
580 bldroot = env.Dir('.').abspath
581 binary = env['BINARYKIND']
583 sourcedir = bldroot + '/source/darwin/%s.app'%binary
584 sourceinfo = bldroot + "/source/darwin/%s.app/Contents/Info.plist"%binary
585 targetinfo = installdir +'/' + "%s.app/Contents/Info.plist"%binary
586 cmd = installdir + '/' +'%s.app'%binary
588 if os.path.isdir(cmd):
590 shutil.copytree(sourcedir, cmd)
591 cmd = "cat %s | sed s/\$\{MACOSX_BUNDLE_SHORT_VERSION_STRING\}/%s/ | "%(sourceinfo,VERSION)
592 cmd += "sed s/\$\{MACOSX_BUNDLE_LONG_VERSION_STRING\}/%s,\ %s/g > %s"%(VERSION,time.strftime("%Y-%b-%d"),targetinfo)
593 commands.getoutput(cmd)
594 cmd = 'cp %s/%s %s/%s.app/Contents/MacOS/%s'%(builddir, binary,installdir, binary, binary)
595 commands.getoutput(cmd)
596 cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/'%(installdir, binary, VERSION)
597 commands.getoutput(cmd)
598 cmd = installdir + '/%s.app/Contents/MacOS/%s'%(binary,VERSION)
600 # blenderplayer doesn't need all the files
601 if binary == 'blender':
602 cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/datafiles'%(installdir, binary, VERSION)
603 commands.getoutput(cmd)
604 cmd = 'cp -R %s/release/datafiles/locale %s/%s.app/Contents/MacOS/%s/datafiles/'%(bldroot,installdir,binary,VERSION)
605 commands.getoutput(cmd)
606 cmd = 'cp -R %s/release/datafiles/fonts %s/%s.app/Contents/MacOS/%s/datafiles/'%(bldroot,installdir,binary,VERSION)
607 commands.getoutput(cmd)
608 if env['WITH_BF_OCIO']:
609 cmd = 'cp -R %s/release/datafiles/colormanagement %s/%s.app/Contents/MacOS/%s/datafiles/'%(bldroot,installdir,binary,VERSION)
610 commands.getoutput(cmd)
611 cmd = 'cp -R %s/release/scripts %s/%s.app/Contents/MacOS/%s/'%(bldroot,installdir,binary,VERSION)
612 commands.getoutput(cmd)
614 if VERSION_RELEASE_CYCLE == "release":
615 cmd = 'rm -rf %s/%s.app/Contents/MacOS/%s/scripts/addons_contrib'%(installdir,binary,VERSION)
616 commands.getoutput(cmd)
618 if env['WITH_BF_CYCLES']:
619 croot = '%s/intern/cycles' % (bldroot)
620 cinstalldir = '%s/%s.app/Contents/MacOS/%s/scripts/addons/cycles' % (installdir,binary,VERSION)
622 cmd = 'mkdir %s' % (cinstalldir)
623 commands.getoutput(cmd)
624 cmd = 'mkdir %s/kernel' % (cinstalldir)
625 commands.getoutput(cmd)
626 cmd = 'mkdir %s/lib' % (cinstalldir)
627 commands.getoutput(cmd)
628 cmd = 'cp -R %s/blender/addon/*.py %s/' % (croot, cinstalldir)
629 commands.getoutput(cmd)
630 cmd = 'cp -R %s/doc/license %s/license' % (croot, cinstalldir)
631 commands.getoutput(cmd)
632 cmd = 'cp -R %s/kernel/*.h %s/kernel/*.cl %s/kernel/*.cu %s/kernel/' % (croot, croot, croot, cinstalldir)
633 commands.getoutput(cmd)
634 cmd = 'cp -R %s/kernel/svm %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, cinstalldir)
635 commands.getoutput(cmd)
636 cmd = 'cp -R %s/../intern/cycles/kernel/*.cubin %s/lib/' % (builddir, cinstalldir)
637 commands.getoutput(cmd)
639 if env['WITH_OSX_STATICPYTHON']:
640 cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/python/'%(installdir,binary, VERSION)
641 commands.getoutput(cmd)
642 cmd = 'unzip -q %s/release/%s -d %s/%s.app/Contents/MacOS/%s/python/'%(libdir,python_zip,installdir,binary,VERSION)
643 commands.getoutput(cmd)
645 cmd = 'chmod +x %s/%s.app/Contents/MacOS/%s'%(installdir,binary, binary)
646 commands.getoutput(cmd)
647 cmd = 'find %s/%s.app -name .svn -prune -exec rm -rf {} \;'%(installdir, binary)
648 commands.getoutput(cmd)
649 cmd = 'find %s/%s.app -name .DS_Store -exec rm -rf {} \;'%(installdir, binary)
650 commands.getoutput(cmd)
651 cmd = 'find %s/%s.app -name __MACOSX -exec rm -rf {} \;'%(installdir, binary)
652 commands.getoutput(cmd)
653 if env['CC'][:-2].endswith('4.6'): # for correct errorhandling with gcc 4.6.x we need the gcc.dylib to link, thus distribute in app-bundle
654 cmd = 'mkdir %s/%s.app/Contents/MacOS/lib'%(installdir, binary)
655 commands.getoutput(cmd)
656 instname = env['BF_CXX']
657 cmd = 'cp %s/lib/libgcc_s.1.dylib %s/%s.app/Contents/MacOS/lib/'%(instname, installdir, binary)
658 commands.getoutput(cmd)
659 cmd = 'install_name_tool -id @executable_path/lib/libgcc_s.1.dylib %s/%s.app/Contents/MacOS/lib/libgcc_s.1.dylib'%(installdir, binary)
660 commands.getoutput(cmd)
661 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)
662 commands.getoutput(cmd)
663 cmd = 'rm -rf %s/set_simulation_threads.app'%(installdir) # first clear omp_num_threads applescript
664 commands.getoutput(cmd)
665 cmd = 'cp -R %s/source/darwin/set_simulation_threads.app %s/'%(bldroot, installdir) # copy the omp_num_threads applescript
666 commands.getoutput(cmd)
668 # extract copy system python, be sure to update other build systems
669 # when making changes to the files that are copied.
670 def my_unixpybundle_print(target, source, env):
673 def UnixPyBundle(target=None, source=None, env=None):
674 # Any Unix except osx
675 #-- VERSION/python/lib/python3.1
680 print 'Install command:', cmd
681 commands.getoutput(cmd)
683 dir = os.path.join(env['BF_INSTALLDIR'], VERSION)
685 lib = env['BF_PYTHON_LIBPATH'].split(os.sep)[-1]
686 target_lib = "lib64" if lib == "lib64" else "lib"
688 py_src = env.subst( env['BF_PYTHON_LIBPATH'] + '/python'+env['BF_PYTHON_VERSION'] )
689 py_target = env.subst( dir + '/python/' + target_lib + '/python'+env['BF_PYTHON_VERSION'] )
691 # This is a bit weak, but dont install if its been installed before, makes rebuilds quite slow.
692 if os.path.exists(py_target):
693 print 'Using existing python from:'
694 print '\t"%s"' % py_target
695 print '\t(skipping copy)\n'
698 # Copied from source/creator/CMakeLists.txt, keep in sync.
699 print 'Install python from:'
700 print '\t"%s" into...' % py_src
701 print '\t"%s"\n' % py_target
703 run("rm -rf '%s'" % py_target)
705 os.makedirs(os.path.dirname(py_target)) # the final part is copied
709 run("cp -R '%s' '%s'" % (py_src, os.path.dirname(py_target)))
710 run("rm -rf '%s/distutils'" % py_target)
711 run("rm -rf '%s/lib2to3'" % py_target)
712 run("rm -rf '%s/config'" % py_target)
714 for f in os.listdir(py_target):
715 if f.startswith("config-"):
716 run("rm -rf '%s/%s'" % (py_target, f))
718 run("rm -rf '%s/site-packages'" % py_target)
719 run("mkdir '%s/site-packages'" % py_target) # python needs it.'
720 run("rm -rf '%s/idlelib'" % py_target)
721 run("rm -rf '%s/tkinter'" % py_target)
722 run("rm -rf '%s/turtledemo'" % py_target)
723 run("rm -r '%s/turtle.py'" % py_target)
724 run("rm -f '%s/lib-dynload/_tkinter.so'" % py_target)
726 if env['WITH_BF_PYTHON_INSTALL_NUMPY']:
727 numpy_src = py_src + "/site-packages/numpy"
728 numpy_target = py_target + "/site-packages/numpy"
730 if os.path.exists(numpy_src):
731 print 'Install numpy from:'
732 print '\t"%s" into...' % numpy_src
733 print '\t"%s"\n' % numpy_target
735 run("cp -R '%s' '%s'" % (numpy_src, os.path.dirname(numpy_target)))
737 print 'Failed to find numpy at %s, skipping copying' % numpy_src
739 run("find '%s' -type d -name 'test' -prune -exec rm -rf {} ';'" % py_target)
740 run("find '%s' -type d -name '__pycache__' -exec rm -rf {} ';'" % py_target)
741 run("find '%s' -name '*.py[co]' -exec rm -rf {} ';'" % py_target)
742 run("find '%s' -name '*.so' -exec strip -s {} ';'" % py_target)
744 #### END ACTION STUFF #########
746 def bsc(env, target, source):
748 bd = os.path.dirname(target[0].abspath)
749 bscfile = '\"'+target[0].abspath+'\"'
750 bscpathcollect = '\"'+bd + os.sep + '*.sbr\"'
751 bscpathtmp = '\"'+bd + os.sep + 'bscmake.tmp\"'
753 os.system('dir /b/s '+bscpathcollect+' >'+bscpathtmp)
755 myfile = open(bscpathtmp[1:-1], 'r')
756 lines = myfile.readlines()
759 newfile = open(bscpathtmp[1:-1], 'w')
761 newfile.write('\"'+l[:-1]+'\"\n')
764 os.system('bscmake /nologo /n /o'+bscfile+' @'+bscpathtmp)
765 os.system('del '+bscpathtmp)
767 class BlenderEnvironment(SConsEnvironment):
769 PyBundleActionAdded = False
771 def BlenderRes(self=None, libname=None, source=None, libtype=['core'], priority=[100]):
773 if not self or not libname or not source:
774 print bc.FAIL+'Cannot continue. Missing argument for BlenderRes '+libname+bc.ENDC
776 if self['OURPLATFORM'] not in ('win32-vc','win32-mingw','linuxcross', 'win64-vc', 'win64-mingw'):
777 print bc.FAIL+'BlenderRes is for windows only!'+bc.END
780 print bc.HEADER+'Configuring resource '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC
782 if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
783 res = lenv.RES('#'+root_build_dir+'lib/'+libname, source)
785 res = lenv.RES(root_build_dir+'lib/'+libname, source)
788 SConsEnvironment.Default(self, res)
789 resources.append(res)
791 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):
793 if not self or not libname or not sources:
794 print bc.FAIL+'Cannot continue. Missing argument for BuildBlenderLib '+libname+bc.ENDC
797 def list_substring(quickie, libname):
799 if libname.find(q) != -1:
803 if list_substring(quickie, libname) or len(quickie)==0:
804 if list_substring(quickdebug, libname):
805 print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname +bc.ENDC+bc.OKBLUE+ " (debug mode)" + bc.ENDC
807 print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname + bc.ENDC
809 lenv.Append(CPPPATH=includes)
810 lenv.Append(CPPDEFINES=defines)
811 if lenv['BF_DEBUG'] or (libname in quickdebug):
812 lenv.Append(CFLAGS = lenv['BF_DEBUG_CFLAGS'])
813 lenv.Append(CCFLAGS = lenv['BF_DEBUG_CCFLAGS'])
814 lenv.Append(CXXFLAGS = lenv['BF_DEBUG_CXXFLAGS'])
816 lenv.Append(CFLAGS = lenv['REL_CFLAGS'])
817 lenv.Append(CCFLAGS = lenv['REL_CCFLAGS'])
818 lenv.Append(CXXFLAGS = lenv['REL_CXXFLAGS'])
819 if lenv['BF_PROFILE']:
820 lenv.Append(CFLAGS = lenv['BF_PROFILE_CFLAGS'])
821 lenv.Append(CCFLAGS = lenv['BF_PROFILE_CCFLAGS'])
822 lenv.Append(CXXFLAGS = lenv['BF_PROFILE_CXXFLAGS'])
824 lenv.Replace(CFLAGS = compileflags)
826 lenv.Replace(CCFLAGS = cc_compileflags)
828 lenv.Replace(CXXFLAGS = cxx_compileflags)
829 if cc_compilerchange:
830 lenv.Replace(CC = cc_compilerchange)
831 if cxx_compilerchange:
832 lenv.Replace(CXX = cxx_compilerchange)
833 lenv.Append(CFLAGS = lenv['C_WARN'])
834 lenv.Append(CCFLAGS = lenv['CC_WARN'])
835 lenv.Append(CXXFLAGS = lenv['CXX_WARN'])
837 if lenv['OURPLATFORM'] == 'win64-vc':
838 lenv.Append(LINKFLAGS = ['/MACHINE:X64'])
840 if lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
842 lenv.Append(CCFLAGS = ['/MTd'])
844 lenv.Append(CCFLAGS = ['/MT'])
846 targetdir = root_build_dir+'lib/' + libname
847 if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
848 targetdir = '#'+targetdir
849 lib = lenv.Library(target= targetdir, source=sources)
850 SConsEnvironment.Default(self, lib) # we add to default target, because this way we get some kind of progress info during build
851 if self['BF_MSVS'] and self['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
852 #if targetdir[0] == '#':
853 # targetdir = targetdir[1:-1]
854 print "! ",targetdir+ '.vcproj' # + self['MSVSPROJECTSUFFIX']
855 vcproject = self.MSVSProject(target = targetdir + '.vcproj', # + self['MSVSPROJECTSUFFIX'],
859 auto_build_solution=0)
860 vcp.append(vcproject)
861 SConsEnvironment.Default(self, vcproject)
863 print bc.WARNING+'Not building '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC+' for '+bc.OKBLUE+'BF_QUICK'+bc.ENDC
864 # note: libs is a global
865 add_lib_to_dict(self, libs, libtype, libname, priority)
867 def BlenderProg(self=None, builddir=None, progname=None, sources=None, libs=None, libpath=None, binarykind=''):
869 print bc.HEADER+'Configuring program '+bc.ENDC+bc.OKGREEN+progname+bc.ENDC
871 lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
872 if lenv['OURPLATFORM'] in ('win32-mingw', 'win64-mingw', 'linuxcross', 'cygwin', 'linux'):
873 lenv.Replace(LINK = '$CXX')
874 if lenv['OURPLATFORM'] in ('win32-vc', 'cygwin', 'win64-vc'):
876 lenv.Prepend(LINKFLAGS = ['/DEBUG','/PDB:'+progname+'.pdb','/NODEFAULTLIB:libcmt'])
877 if lenv['OURPLATFORM']=='linux':
878 if lenv['WITH_BF_PYTHON']:
879 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
880 if lenv['OURPLATFORM']=='sunos5':
881 if lenv['WITH_BF_PYTHON']:
882 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
883 if lenv['CXX'].endswith('CC'):
884 lenv.Replace(LINK = '$CXX')
885 if lenv['OURPLATFORM']=='darwin':
886 if lenv['WITH_BF_PYTHON']:
887 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
888 lenv.Append(LINKFLAGS = lenv['BF_OPENGL_LINKFLAGS'])
889 if lenv['BF_PROFILE']:
890 lenv.Append(LINKFLAGS = lenv['BF_PROFILE_LINKFLAGS'])
891 if root_build_dir[0]==os.sep or root_build_dir[1]==':':
892 lenv.Append(LIBPATH=root_build_dir + '/lib')
893 lenv.Append(LIBPATH=libpath)
894 lenv.Append(LIBS=libs)
895 if lenv['WITH_BF_QUICKTIME']:
896 lenv.Append(LIBS = lenv['BF_QUICKTIME_LIB'])
897 lenv.Append(LIBPATH = lenv['BF_QUICKTIME_LIBPATH'])
898 prog = lenv.Program(target=builddir+'bin/'+progname, source=sources)
899 if lenv['BF_DEBUG'] and lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc') and lenv['BF_BSC']:
900 f = lenv.File(progname + '.bsc', builddir)
901 brs = lenv.Command(f, prog, [bsc])
902 SConsEnvironment.Default(self, brs)
903 SConsEnvironment.Default(self, prog)
904 if self['BF_MSVS'] and self['OURPLATFORM'] in ('win32-vc', 'win64-vc') and progname == 'blender':
905 print "! ",builddir + "/" + progname + '.sln'
906 sln = self.MSVSProject(target = builddir + "/" + progname + '.sln',
909 SConsEnvironment.Default(self, sln)
910 program_list.append(prog)
911 if lenv['OURPLATFORM']=='darwin':
912 lenv['BINARYKIND'] = binarykind
913 lenv.AddPostAction(prog,Action(AppIt,strfunction=my_appit_print))
914 elif os.sep == '/' and lenv['OURPLATFORM'] != 'linuxcross': # any unix (except cross-compilation)
915 if lenv['WITH_BF_PYTHON']:
916 if (not lenv['WITHOUT_BF_INSTALL'] and
917 not lenv['WITHOUT_BF_PYTHON_INSTALL'] and
918 not lenv['WITHOUT_BF_PYTHON_UNPACK'] and
919 not BlenderEnvironment.PyBundleActionAdded):
920 lenv.AddPostAction(prog,Action(UnixPyBundle,strfunction=my_unixpybundle_print))
921 BlenderEnvironment.PyBundleActionAdded = True
922 elif lenv['OURPLATFORM'].startswith('win') or lenv['OURPLATFORM'] == 'linuxcross': # windows or cross-compilation
923 if lenv['WITH_BF_PYTHON']:
924 if (not lenv['WITHOUT_BF_PYTHON_INSTALL'] and
925 not lenv['WITHOUT_BF_PYTHON_UNPACK'] and
926 not BlenderEnvironment.PyBundleActionAdded):
927 lenv.AddPostAction(prog,Action(WinPyBundle,strfunction=my_winpybundle_print))
928 BlenderEnvironment.PyBundleActionAdded = True
931 def Glob(lenv, pattern):
932 path = string.replace(GetBuildPath(lenv,'SConscript'),'SConscript', '')
934 for i in glob.glob(path + pattern):
935 files.append(string.replace(i, path, ''))