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
23 from SCons.Script.SConscript import SConsEnvironment
29 bc = bcolors.bcolors()
31 Split = SCons.Util.Split
32 Action = SCons.Action.Action
33 Builder = SCons.Builder.Builder
34 GetBuildPath = SConsEnvironment.GetBuildPath
38 quickie = None # Anything else than None if BF_QUICK has been passed
39 quicklist = [] # The list of libraries/programs to compile during a quickie
40 program_list = [] # A list holding Nodes to final binaries, used to create installs
46 blenderdeps = [] # don't manipulate this one outside this module!
48 ##### LIB STUFF ##########
50 possible_types = ['core'] # can be set in ie. SConstruct
57 for pt in possible_types:
60 # helper func for add_lib_to_dict
61 def internal_lib_to_dict(dict = None, libtype = None, libname = None, priority = 100):
62 if not libname in dict[libtype]:
65 if dict[libtype].has_key(priority):
66 priority = priority + 1
69 dict[libtype][priority] = libname
71 # libtype and priority can both be lists, for defining lib in multiple places
72 def add_lib_to_dict(dict = None, libtype = None, libname = None, priority = 100):
73 if not dict or not libtype or not libname:
74 print "Passed wrong arg"
77 if type(libtype) is str and type(priority) is int:
78 internal_lib_to_dict(dict, libtype, libname, priority)
79 elif type(libtype) is list and type(priority) is list:
80 if len(libtype)==len(priority):
81 for lt, p in zip(libtype, priority):
82 internal_lib_to_dict(dict, lt, libname, p)
84 print "libtype and priority lists are unequal in length"
87 print "Wrong type combinations for libtype and priority. Only str and int or list and list"
90 def create_blender_liblist(lenv = None, libtype = None):
91 if not lenv or not libtype:
95 if libtype in possible_types:
97 for k,v in libs[libtype].iteritems():
100 curlib = libs[libtype]
103 lst.append('#' + root_build_dir + 'lib/'+lenv['LIBPREFIX'] + v + lenv['LIBSUFFIX'])
107 ## TODO: static linking
108 def setup_staticlibs(lenv):
110 #here libs for static linking
114 lenv['BF_PYTHON_LIBPATH'],
115 lenv['BF_OPENGL_LIBPATH'],
116 lenv['BF_SDL_LIBPATH'],
117 lenv['BF_JPEG_LIBPATH'],
118 lenv['BF_PNG_LIBPATH'],
119 lenv['BF_ZLIB_LIBPATH'],
120 lenv['BF_ICONV_LIBPATH']
122 libincs += Split(lenv['BF_OPENEXR_LIBPATH'])
123 libincs += Split(lenv['BF_FFMPEG_LIBPATH'])
125 if lenv['WITH_BF_INTERNATIONAL']:
126 libincs += Split(lenv['BF_GETTEXT_LIBPATH'])
127 libincs += Split(lenv['BF_FREETYPE_LIBPATH'])
128 if lenv['WITH_BF_OPENAL']:
129 libincs += Split(lenv['BF_OPENAL_LIBPATH'])
131 if lenv['WITH_BF_STATICOPENGL']:
132 statlibs += Split(lenv['BF_OPENGL_LIB_STATIC'])
134 if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross'):
135 libincs += Split(lenv['BF_PTHREADS_LIBPATH'])
137 return statlibs, libincs
139 def setup_syslibs(lenv):
146 if lenv['BF_DEBUG']==1 and lenv['OURPLATFORM'] in ('win32-vc'):
147 syslibs.append(lenv['BF_PYTHON_LIB']+'_d')
149 syslibs.append(lenv['BF_PYTHON_LIB'])
150 if lenv['WITH_BF_INTERNATIONAL']:
151 syslibs += Split(lenv['BF_FREETYPE_LIB'])
152 syslibs += Split(lenv['BF_GETTEXT_LIB'])
153 if lenv['WITH_BF_OPENAL']:
154 syslibs += Split(lenv['BF_OPENAL_LIB'])
155 if lenv['WITH_BF_OPENMP'] and lenv['CC'] != 'icc':
157 if lenv['WITH_BF_ICONV']:
158 syslibs += Split(lenv['BF_ICONV_LIB'])
159 if lenv['WITH_BF_OPENEXR']:
160 syslibs += Split(lenv['BF_OPENEXR_LIB'])
161 if lenv['WITH_BF_FFMPEG']:
162 syslibs += Split(lenv['BF_FFMPEG_LIB'])
163 syslibs += Split(lenv['BF_SDL_LIB'])
164 if not lenv['WITH_BF_STATICOPENGL']:
165 syslibs += Split(lenv['BF_OPENGL_LIB'])
166 if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw','linuxcross'):
167 syslibs += Split(lenv['BF_PTHREADS_LIB'])
169 syslibs += Split(lenv['LLIBS'])
173 def propose_priorities():
174 print bc.OKBLUE+"Priorities:"+bc.ENDC
175 for t in possible_types:
176 print bc.OKGREEN+"\t"+t+bc.ENDC
179 for k,v in libs[t].iteritems():
185 #for p,v in sorted(libs[t].iteritems()):
186 print "\t\t",new_priority, v
189 ## TODO: see if this can be made in an emitter
190 def buildinfo(lenv, build_type):
192 Generate a buildinfo object
194 build_date = time.strftime ("%Y-%m-%d")
195 build_time = time.strftime ("%H:%M:%S")
196 build_rev = os.popen('svnversion').read()[:-1] # remove \n
199 if lenv['BF_BUILDINFO']==1: #user_options_dict['USE_BUILDINFO'] == 1:
200 if sys.platform=='win32':
201 build_info_file = open("source/creator/winbuildinfo.h", 'w')
202 build_info_file.write("char *build_date=\"%s\";\n"%build_date)
203 build_info_file.write("char *build_time=\"%s\";\n"%build_time)
204 build_info_file.write("char *build_rev=\"%s\";\n"%build_rev)
205 build_info_file.write("char *build_platform=\"win32\";\n")
206 build_info_file.write("char *build_type=\"dynamic\";\n")
207 build_info_file.close()
208 lenv.Append (CPPDEFINES = ['NAN_BUILDINFO', 'BUILD_DATE'])
210 lenv.Append (CPPDEFINES = ['BUILD_TIME=\'"%s"\''%(build_time),
211 'BUILD_DATE=\'"%s"\''%(build_date),
212 'BUILD_TYPE=\'"dynamic"\'',
213 'BUILD_REV=\'"%s"\''%(build_rev),
215 'BUILD_PLATFORM=\'"%s"\''%(sys.platform)])
216 obj = [lenv.Object (root_build_dir+'source/creator/%s_buildinfo'%build_type,
217 [root_build_dir+'source/creator/buildinfo.c'])]
220 ##### END LIB STUFF ############
222 ##### ACTION STUFF #############
224 def my_compile_print(target, source, env):
225 a = '%s' % (source[0])
226 d, f = os.path.split(a)
227 return bc.OKBLUE+"Compiling"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
229 def my_moc_print(target, source, env):
230 a = '%s' % (source[0])
231 d, f = os.path.split(a)
232 return bc.OKBLUE+"Creating MOC"+bc.ENDC+ " ==> '"+bc.OKGREEN+"%s" %(f) + "'"+bc.ENDC
234 def my_linking_print(target, source, env):
235 t = '%s' % (target[0])
236 d, f = os.path.split(t)
237 return bc.OKBLUE+"Linking library"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
239 def my_program_print(target, source, env):
240 t = '%s' % (target[0])
241 d, f = os.path.split(t)
242 return bc.OKBLUE+"Linking program"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
245 static_lib = SCons.Tool.createStaticLibBuilder(env)
246 program = SCons.Tool.createProgBuilder(env)
248 env['BUILDERS']['Library'] = static_lib
249 env['BUILDERS']['StaticLibrary'] = static_lib
250 env['BUILDERS']['Program'] = program
252 def set_quiet_output(env):
253 mycaction = Action("$CCCOM", strfunction=my_compile_print)
254 myshcaction = Action("$SHCCCOM", strfunction=my_compile_print)
255 mycppaction = Action("$CXXCOM", strfunction=my_compile_print)
256 myshcppaction = Action("$SHCXXCOM", strfunction=my_compile_print)
257 mylibaction = Action("$ARCOM", strfunction=my_linking_print)
258 mylinkaction = Action("$LINKCOM", strfunction=my_program_print)
260 static_ob, shared_ob = SCons.Tool.createObjBuilders(env)
261 static_ob.add_action('.c', mycaction)
262 static_ob.add_action('.cpp', mycppaction)
263 shared_ob.add_action('.c', myshcaction)
264 shared_ob.add_action('.cpp', myshcppaction)
266 static_lib = SCons.Builder.Builder(action = mylibaction,
267 emitter = '$LIBEMITTER',
268 prefix = '$LIBPREFIX',
269 suffix = '$LIBSUFFIX',
270 src_suffix = '$OBJSUFFIX',
271 src_builder = 'StaticObject')
273 program = SCons.Builder.Builder(action = mylinkaction,
274 emitter = '$PROGEMITTER',
275 prefix = '$PROGPREFIX',
276 suffix = '$PROGSUFFIX',
277 src_suffix = '$OBJSUFFIX',
278 src_builder = 'Object',
279 target_scanner = SCons.Defaults.ProgScan)
281 env['BUILDERS']['Object'] = static_ob
282 env['BUILDERS']['StaticObject'] = static_ob
283 env['BUILDERS']['StaticLibrary'] = static_lib
284 env['BUILDERS']['Library'] = static_lib
285 env['BUILDERS']['Program'] = program
287 def my_appit_print(target, source, env):
288 a = '%s' % (target[0])
289 d, f = os.path.split(a)
290 return "making bundle for " + f
292 def AppIt(target=None, source=None, env=None):
298 a = '%s' % (target[0])
299 builddir, b = os.path.split(a)
301 bldroot = env.Dir('.').abspath
302 binary = env['BINARYKIND']
305 print bc.OKBLUE+"no bundle for verse"+bc.ENDC
309 sourcedir = bldroot + '/source/darwin/%s.app'%binary
310 sourceinfo = bldroot + "/source/darwin/%s.app/Contents/Info.plist"%binary
311 targetinfo = builddir +'/' + "%s.app/Contents/Info.plist"%binary
312 cmd = builddir + '/' +'%s.app'%binary
314 if os.path.isdir(cmd):
316 shutil.copytree(sourcedir, cmd)
317 cmd = "cat %s | sed s/VERSION/`cat release/VERSION`/ | sed s/DATE/`date +'%%Y-%%b-%%d'`/ > %s"%(sourceinfo,targetinfo)
318 commands.getoutput(cmd)
319 cmd = 'cp %s/%s %s/%s.app/Contents/MacOS/%s'%(builddir, binary,builddir, binary, binary)
320 commands.getoutput(cmd)
321 cmd = 'mkdir %s/%s.app/Contents/MacOS/.blender/'%(builddir, binary)
323 commands.getoutput(cmd)
324 cmd = builddir + '/%s.app/Contents/MacOS/.blender'%binary
325 shutil.copy(bldroot + '/bin/.blender/.bfont.ttf', cmd)
326 shutil.copy(bldroot + '/bin/.blender/.Blanguages', cmd)
327 cmd = 'cp -R %s/bin/.blender/locale %s/%s.app/Contents/Resources/'%(bldroot,builddir,binary)
328 commands.getoutput(cmd)
329 cmd = 'cp -R %s/bin/.blender/locale %s/%s.app/Contents/MacOS/.blender/'%(bldroot,builddir,binary)
330 commands.getoutput(cmd)
331 cmd = 'cp %s/bin/.blender/.Blanguages %s/%s.app/Contents/Resources/'%(bldroot,builddir,binary)
332 commands.getoutput(cmd)
333 cmd = 'cp -R %s/release/scripts %s/%s.app/Contents/MacOS/.blender/'%(bldroot,builddir,binary)
334 commands.getoutput(cmd)
335 cmd = 'chmod +x %s/%s.app/Contents/MacOS/%s'%(builddir,binary, binary)
336 commands.getoutput(cmd)
337 cmd = 'find %s/%s.app -name .svn -prune -exec rm -rf {} \;'%(builddir, binary)
338 commands.getoutput(cmd)
339 cmd = 'find %s/%s.app -name .DS_Store -exec rm -rf {} \;'%(builddir, binary)
340 commands.getoutput(cmd)
342 #### END ACTION STUFF #########
344 def bsc(env, target, source):
346 bd = os.path.dirname(target[0].abspath)
347 bscfile = '\"'+target[0].abspath+'\"'
348 bscpathcollect = '\"'+bd + os.sep + '*.sbr\"'
349 bscpathtmp = '\"'+bd + os.sep + 'bscmake.tmp\"'
351 os.system('dir /b/s '+bscpathcollect+' >'+bscpathtmp)
353 myfile = open(bscpathtmp[1:-1], 'r')
354 lines = myfile.readlines()
357 newfile = open(bscpathtmp[1:-1], 'w')
359 newfile.write('\"'+l[:-1]+'\"\n')
362 os.system('bscmake /nologo /n /o'+bscfile+' @'+bscpathtmp)
363 os.system('del '+bscpathtmp)
365 class BlenderEnvironment(SConsEnvironment):
367 def BlenderRes(self=None, libname=None, source=None, libtype=['core'], priority=[100]):
369 if not self or not libname or not source:
370 print bc.FAIL+'Cannot continue. Missing argument for BlenderRes '+libname+bc.ENDC
372 if self['OURPLATFORM'] not in ('win32-vc','win32-mingw','linuxcross'):
373 print bc.FAIL+'BlenderRes is for windows only!'+bc.END
376 print bc.HEADER+'Configuring resource '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC
378 res = lenv.RES('#'+root_build_dir+'lib/'+libname, source)
380 SConsEnvironment.Default(self, res)
381 resources.append(res)
383 def BlenderLib(self=None, libname=None, sources=None, includes=[], defines=[], libtype='common', priority = 100, compileflags=None):
384 if not self or not libname or not sources:
385 print bc.FAIL+'Cannot continue. Missing argument for BuildBlenderLib '+libname+bc.ENDC
387 if libname in quickie or len(quickie)==0:
388 if libname in quickdebug:
389 print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname +bc.ENDC+bc.OKBLUE+ " (debug mode)" + bc.ENDC
391 print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname + bc.ENDC
393 lenv.Append(CPPPATH=includes)
394 lenv.Append(CPPDEFINES=defines)
395 if lenv['WITH_BF_GAMEENGINE']:
396 lenv.Append(CPPDEFINES=['GAMEBLENDER=1'])
397 if lenv['WITH_BF_BULLET']:
398 lenv.Append(CPPDEFINES=['WITH_BULLET=1'])
400 # CXXFLAGS defaults to CCFLAGS, therefore
401 # we Replace() rather than Append() to CXXFLAGS the first time
402 lenv.Replace(CXXFLAGS = lenv['CCFLAGS'])
403 if lenv['BF_DEBUG'] or (libname in quickdebug):
404 lenv.Append(CCFLAGS = Split(lenv['BF_DEBUG_FLAGS']))
405 lenv.Append( CXXFLAGS = Split(lenv['BF_DEBUG_FLAGS']))
407 lenv.Append(CCFLAGS = lenv['REL_CFLAGS'])
408 lenv.Append(CXXFLAGS = lenv['REL_CCFLAGS'])
409 if lenv['BF_PROFILE']:
410 lenv.Append(CCFLAGS = Split(lenv['BF_PROFILE_FLAGS']),
411 CXXFLAGS = Split(lenv['BF_PROFILE_FLAGS']))
413 lenv.Append(CCFLAGS = compileflags)
414 lenv.Append(CXXFLAGS = compileflags)
415 lenv.Append(CCFLAGS = Split(lenv['C_WARN']))
416 lenv.Append(CXXFLAGS = Split(lenv['CC_WARN']))
417 lib = lenv.Library(target= '#'+root_build_dir+'lib/'+libname, source=sources)
418 SConsEnvironment.Default(self, lib) # we add to default target, because this way we get some kind of progress info during build
420 print bc.WARNING+'Not building '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC+' for '+bc.OKBLUE+'BF_QUICK'+bc.ENDC
421 # note: libs is a global
422 add_lib_to_dict(libs, libtype, libname, priority)
424 def BlenderProg(self=None, builddir=None, progname=None, sources=None, includes=None, libs=None, libpath=None, binarykind=''):
425 print bc.HEADER+'Configuring program '+bc.ENDC+bc.OKGREEN+progname+bc.ENDC
427 if lenv['OURPLATFORM'] in ['win32-vc', 'cygwin']:
428 lenv.Append(LINKFLAGS = Split(lenv['PLATFORM_LINKFLAGS']))
430 lenv.Prepend(LINKFLAGS = ['/DEBUG','/PDB:'+progname+'.pdb'])
431 if lenv['OURPLATFORM']=='linux2':
432 lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
433 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
434 if lenv['OURPLATFORM']=='sunos5':
435 lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
436 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
437 if lenv['CXX'].endswith('CC'):
438 lenv.Replace(LINK = '$CXX')
439 if lenv['OURPLATFORM']=='darwin':
440 lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
441 lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
442 lenv.Append(LINKFLAGS = lenv['BF_OPENGL_LINKFLAGS'])
443 if lenv['BF_PROFILE']:
444 lenv.Append(LINKFLAGS = lenv['BF_PROFILE_FLAGS'])
445 lenv.Append(CPPPATH=includes)
446 lenv.Append(LIBPATH=libpath)
447 lenv.Append(LIBS=libs)
448 if lenv['WITH_BF_QUICKTIME']:
449 lenv.Append(LIBS = lenv['BF_QUICKTIME_LIB'])
450 lenv.Append(LIBPATH = lenv['BF_QUICKTIME_LIBPATH'])
451 prog = lenv.Program(target=builddir+'bin/'+progname, source=sources)
452 if lenv['BF_DEBUG'] and lenv['OURPLATFORM']=='win32-vc' and lenv['BF_BSC']:
453 f = lenv.File(progname + '.bsc', builddir)
454 brs = lenv.Command(f, prog, [bsc])
455 SConsEnvironment.Default(self, brs)
456 SConsEnvironment.Default(self, prog)
457 program_list.append(prog)
458 if lenv['OURPLATFORM']=='darwin':
459 lenv['BINARYKIND'] = binarykind
460 lenv.AddPostAction(prog,Action(AppIt,strfunction=my_appit_print))
463 def Glob(lenv, pattern):
464 path = string.replace(GetBuildPath(lenv,'SConscript'),'SConscript', '')
466 for i in glob.glob(path + pattern):
467 files.append(string.replace(i, path, ''))