some of the .po file had empty msgids and multilline comments from
[blender.git] / 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 import os.path
17 import string
18 import glob
19 import time
20 import sys
21
22 from SCons.Script.SConscript import SConsEnvironment
23 import SCons.Action
24 import SCons.Util
25 import SCons.Builder
26 import SCons.Tool
27 import bcolors
28 bc = bcolors.bcolors()
29
30 Split = SCons.Util.Split
31 Action = SCons.Action.Action
32 Builder = SCons.Builder.Builder
33 GetBuildPath = SConsEnvironment.GetBuildPath
34
35 # a few globals
36 root_build_dir = ''
37 quickie = None # Anything else than None if BF_QUICK has been passed
38 quicklist = [] # The list of libraries/programs to compile during a quickie
39 program_list = [] # A list holding Nodes to final binaries, used to create installs
40 arguments = None
41 targets = None
42 resources = []
43
44 #some internals
45 blenderdeps = [] # don't manipulate this one outside this module!
46
47 ##### LIB STUFF ##########
48
49 possible_types = ['core'] # can be set in ie. SConstruct
50 libs = {}
51
52 def getresources():
53     return resources
54
55 def init_lib_dict():
56     for pt in possible_types:
57         libs[pt] = {}
58
59 # helper func for add_lib_to_dict
60 def internal_lib_to_dict(dict = None, libtype = None, libname = None, priority = 100):
61     if not libname in dict[libtype]:
62         done = None
63         while not done:
64             if dict[libtype].has_key(priority):
65                 priority = priority + 1
66             else:
67                 done = True
68         dict[libtype][priority] = libname
69
70 # libtype and priority can both be lists, for defining lib in multiple places
71 def add_lib_to_dict(dict = None, libtype = None, libname = None, priority = 100):
72     if not dict or not libtype or not libname:
73         print "Passed wrong arg"
74         Exit()
75
76     if type(libtype) is str and type(priority) is int:
77         internal_lib_to_dict(dict, libtype, libname, priority)
78     elif type(libtype) is list and type(priority) is list:
79         if len(libtype)==len(priority):
80             for lt, p in zip(libtype, priority):
81                 internal_lib_to_dict(dict, lt, libname, p)
82         else:
83             print "libtype and priority lists are unequal in length"
84             Exit()
85     else:
86         print "Wrong type combinations for libtype and priority. Only str and int or list and list"
87         Exit()
88
89 def create_blender_liblist(lenv = None, libtype = None):
90     if not lenv or not libtype:
91         print "missing arg"
92
93     lst = []
94     if libtype in possible_types:
95         sortlist = []
96         for k,v in libs[libtype].iteritems():
97             sortlist.append(k)
98         sortlist.sort()
99         curlib = libs[libtype]
100         for sk in sortlist:
101             v = curlib[sk]
102             lst.append('#' + root_build_dir + 'lib/'+lenv['LIBPREFIX'] + v + lenv['LIBSUFFIX'])
103
104     return lst
105
106 ## TODO: static linking
107 def setup_staticlibs(lenv):
108     statlibs = [
109         #here libs for static linking
110     ]
111     libincs = [
112         '/usr/lib',
113         lenv['BF_PYTHON_LIBPATH'],
114         lenv['BF_OPENGL_LIBPATH'],
115         lenv['BF_SDL_LIBPATH'],
116         lenv['BF_JPEG_LIBPATH'],
117         lenv['BF_PNG_LIBPATH'],
118         lenv['BF_ZLIB_LIBPATH'],
119         lenv['BF_ICONV_LIBPATH']
120         ]
121     libincs += Split(lenv['BF_OPENEXR_LIBPATH'])
122
123     if lenv['WITH_BF_INTERNATIONAL']:
124         libincs += Split(lenv['BF_GETTEXT_LIBPATH'])
125         libincs += Split(lenv['BF_FREETYPE_LIBPATH'])
126     if lenv['WITH_BF_OPENAL']:
127         libincs += Split(lenv['BF_OPENAL_LIBPATH'])
128
129     if lenv['WITH_BF_STATICOPENGL']:
130         statlibs += Split(lenv['BF_OPENGL_LIB_STATIC'])
131
132     if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross'):
133         libincs += Split(lenv['BF_PTHREADS_LIBPATH'])
134
135     return statlibs, libincs
136
137 def setup_syslibs(lenv):
138     syslibs = [
139         lenv['BF_PYTHON_LIB'],
140         lenv['BF_JPEG_LIB'],
141         lenv['BF_PNG_LIB'],
142         lenv['BF_ZLIB_LIB']
143         ]
144     if lenv['WITH_BF_INTERNATIONAL']:
145         syslibs += Split(lenv['BF_FREETYPE_LIB'])
146         syslibs += Split(lenv['BF_GETTEXT_LIB'])
147     if lenv['WITH_BF_OPENAL']:
148        syslibs += Split(lenv['BF_OPENAL_LIB'])
149     if lenv['OURPLATFORM']=='win32vc':
150         syslibs += Split(lenv['BF_ICONV_LIB'])
151     if lenv['WITH_BF_OPENEXR']:
152         syslibs += Split(lenv['BF_OPENEXR_LIB'])
153     if lenv['WITH_BF_FFMPEG']:
154         syslibs += Split(lenv['BF_FFMPEG_LIB'])
155     syslibs += Split(lenv['BF_SDL_LIB'])
156     if not lenv['WITH_BF_STATICOPENGL']:
157         syslibs += Split(lenv['BF_OPENGL_LIB'])
158     if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw','linuxcross'):
159         syslibs += Split(lenv['BF_PTHREADS_LIB'])
160
161     syslibs += Split(lenv['LLIBS'])
162
163     return syslibs
164
165 def propose_priorities():
166     print bc.OKBLUE+"Priorities:"+bc.ENDC
167     for t in possible_types:
168         print bc.OKGREEN+"\t"+t+bc.ENDC
169         new_priority = 0
170         sortlist = []
171         for k,v in libs[t].iteritems():
172             sortlist.append(k)
173         sortlist.sort()
174         curlib = libs[t]
175         for sk in sortlist:
176             v = curlib[sk]
177             #for p,v in sorted(libs[t].iteritems()):
178             print "\t\t",new_priority, v
179             new_priority += 5
180
181 ## TODO: see if this can be made in an emitter
182 def buildinfo(lenv, build_type):
183     """
184     Generate a buildinfo object
185     """
186     build_date = time.strftime ("%Y-%m-%d")
187     build_time = time.strftime ("%H:%M:%S")
188     obj = []
189     if lenv['BF_BUILDINFO']==1: #user_options_dict['USE_BUILDINFO'] == 1:
190         if sys.platform=='win32':
191             build_info_file = open("source/creator/winbuildinfo.h", 'w')
192             build_info_file.write("char *build_date=\"%s\";\n"%build_date)
193             build_info_file.write("char *build_time=\"%s\";\n"%build_time)
194             build_info_file.write("char *build_platform=\"win32\";\n")
195             build_info_file.write("char *build_type=\"dynamic\";\n")
196             build_info_file.close()
197             lenv.Append (CPPDEFINES = ['NAN_BUILDINFO', 'BUILD_DATE'])
198         else:
199             lenv.Append (CPPDEFINES = ['BUILD_TIME=\'"%s"\''%(build_time),
200                                         'BUILD_DATE=\'"%s"\''%(build_date),
201                                         'BUILD_TYPE=\'"dynamic"\'',
202                                         'NAN_BUILDINFO',
203                                         'BUILD_PLATFORM=\'"%s"\''%(sys.platform)])
204         obj = [lenv.Object (root_build_dir+'source/creator/%s_buildinfo'%build_type,
205                         [root_build_dir+'source/creator/buildinfo.c'])]
206     return obj
207
208 ##### END LIB STUFF ############
209
210 ##### ACTION STUFF #############
211
212 def my_compile_print(target, source, env):
213     a = '%s' % (source[0])
214     d, f = os.path.split(a)
215     return bc.OKBLUE+"Compiling"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
216
217 def my_moc_print(target, source, env):
218     a = '%s' % (source[0])
219     d, f = os.path.split(a)
220     return bc.OKBLUE+"Creating MOC"+bc.ENDC+ " ==> '"+bc.OKGREEN+"%s" %(f) + "'"+bc.ENDC
221
222 def my_linking_print(target, source, env):
223     t = '%s' % (target[0])
224     d, f = os.path.split(t)
225     return bc.OKBLUE+"Linking library"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
226
227 def my_program_print(target, source, env):
228     t = '%s' % (target[0])
229     d, f = os.path.split(t)
230     return bc.OKBLUE+"Linking program"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
231
232 def msvc_hack(env):
233     static_lib = SCons.Tool.createStaticLibBuilder(env)
234     program = SCons.Tool.createProgBuilder(env)
235     
236     env['BUILDERS']['Library'] = static_lib
237     env['BUILDERS']['StaticLibrary'] = static_lib
238     env['BUILDERS']['Program'] = program
239         
240 def set_quiet_output(env):
241     mycaction = Action("$CCCOM", strfunction=my_compile_print)
242     myshcaction = Action("$SHCCCOM", strfunction=my_compile_print)
243     mycppaction = Action("$CXXCOM", strfunction=my_compile_print)
244     myshcppaction = Action("$SHCXXCOM", strfunction=my_compile_print)
245     mylibaction = Action("$ARCOM", strfunction=my_linking_print)
246     mylinkaction = Action("$LINKCOM", strfunction=my_program_print)
247
248     static_ob, shared_ob = SCons.Tool.createObjBuilders(env)
249     static_ob.add_action('.c', mycaction)
250     static_ob.add_action('.cpp', mycppaction)
251     shared_ob.add_action('.c', myshcaction)
252     shared_ob.add_action('.cpp', myshcppaction)
253
254     static_lib = SCons.Builder.Builder(action = mylibaction,
255                                        emitter = '$LIBEMITTER',
256                                        prefix = '$LIBPREFIX',
257                                        suffix = '$LIBSUFFIX',
258                                        src_suffix = '$OBJSUFFIX',
259                                        src_builder = 'StaticObject')
260
261     program = SCons.Builder.Builder(action = mylinkaction,
262                                     emitter = '$PROGEMITTER',
263                                     prefix = '$PROGPREFIX',
264                                     suffix = '$PROGSUFFIX',
265                                     src_suffix = '$OBJSUFFIX',
266                                     src_builder = 'Object',
267                                     target_scanner = SCons.Defaults.ProgScan)
268
269     env['BUILDERS']['Object'] = static_ob
270     env['BUILDERS']['StaticObject'] = static_ob
271     env['BUILDERS']['StaticLibrary'] = static_lib
272     env['BUILDERS']['Library'] = static_lib
273     env['BUILDERS']['Program'] = program
274
275 def  my_appit_print(target, source, env):
276     a = '%s' % (target[0])
277     d, f = os.path.split(a)
278     return "making bundle for " + f
279
280 def AppIt(target=None, source=None, env=None):
281     import shutil
282     import commands
283     import os.path
284     
285     a = '%s' % (target[0])
286     builddir, b = os.path.split(a)
287     bldroot = env.Dir('.').abspath
288     binary = env['BINARYKIND']
289     
290     sourcedir = bldroot + '/source/darwin/%s.app'%binary
291     sourceinfo = bldroot + "/source/darwin/%s.app/Contents/Info.plist"%binary
292     targetinfo = builddir +'/' + "%s.app/Contents/Info.plist"%binary
293     cmd = builddir + '/' +'%s.app'%binary
294     
295     if os.path.isdir(cmd):
296         shutil.rmtree(cmd)
297     shutil.copytree(sourcedir, cmd)
298     cmd = "cat %s | sed s/VERSION/`cat release/VERSION`/ | sed s/DATE/`date +'%%Y-%%b-%%d'`/ > %s"%(sourceinfo,targetinfo)
299     commands.getoutput(cmd)
300     cmd = 'cp %s/%s %s/%s.app/Contents/MacOS/%s'%(builddir, binary,builddir, binary, binary)
301     commands.getoutput(cmd)
302     cmd = 'mkdir %s/%s.app/Contents/MacOS/.blender/'%(builddir, binary)
303     print cmd
304     commands.getoutput(cmd)
305     cmd = builddir + '/%s.app/Contents/MacOS/.blender'%binary
306     shutil.copy(bldroot + '/bin/.blender/.bfont.ttf', cmd)
307     shutil.copy(bldroot + '/bin/.blender/.Blanguages', cmd)
308     cmd = 'cp -R %s/bin/.blender/locale %s/%s.app/Contents/Resources/'%(bldroot,builddir,binary)
309     commands.getoutput(cmd) 
310     cmd = 'cp -R %s/bin/.blender/locale %s/%s.app/Contents/MacOS/.blender/'%(bldroot,builddir,binary)
311     commands.getoutput(cmd) 
312     cmd = 'cp %s/bin/.blender/.Blanguages %s/%s.app/Contents/Resources/'%(bldroot,builddir,binary)
313     commands.getoutput(cmd) 
314     cmd = 'cp -R %s/release/scripts %s/%s.app/Contents/MacOS/.blender/'%(bldroot,builddir,binary)
315     commands.getoutput(cmd)
316     cmd = 'chmod +x  %s/%s.app/Contents/MacOS/%s'%(builddir,binary, binary)
317     commands.getoutput(cmd)
318     cmd = 'find %s/%s.app -name CVS -prune -exec rm -rf {} \;'%(builddir, binary)
319     commands.getoutput(cmd)
320     cmd = 'find %s/%s.app -name .DS_Store -exec rm -rf {} \;'%(builddir, binary)
321     commands.getoutput(cmd)
322
323 #### END ACTION STUFF #########
324
325 class BlenderEnvironment(SConsEnvironment):
326
327     def BlenderRes(self=None, libname=None, source=None, libtype=['core'], priority=[100]):
328         global libs
329         if not self or not libname or not source:
330             print bc.FAIL+'Cannot continue.  Missing argument for BlenderRes '+libname+bc.ENDC
331             Exit()
332         if self['OURPLATFORM'] not in ('win32-vc','win32-mingw','linuxcross'):
333             print bc.FAIL+'BlenderRes is for windows only!'+bc.END
334             Exit()
335         
336         print bc.HEADER+'Configuring resource '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC
337         lenv = self.Copy()
338         res = lenv.RES('#'+root_build_dir+'lib/'+libname, source)
339       
340         SConsEnvironment.Default(self, res)
341         resources.append(res)
342
343     def BlenderLib(self=None, libname=None, sources=None, includes=[], defines=[], libtype='common', priority = 100, compileflags=None):
344         if not self or not libname or not sources:
345             print bc.FAIL+'Cannot continue. Missing argument for BuildBlenderLib '+libname+bc.ENDC
346             Exit()
347         if libname in quickie or len(quickie)==0:
348             if libname in quickdebug: 
349                 print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname +bc.ENDC+bc.OKBLUE+ " (debug mode)" + bc.ENDC
350             else:
351                 print bc.HEADER+'Configuring library '+bc.ENDC+bc.OKGREEN+libname + bc.ENDC
352             lenv = self.Copy()
353             lenv.Append(CPPPATH=includes)
354             lenv.Append(CPPDEFINES=defines)
355             if lenv['WITH_BF_GAMEENGINE']:
356                     lenv.Append(CPPDEFINES=['GAMEBLENDER=1'])
357             if lenv['BF_DEBUG'] or (libname in quickdebug):
358                     lenv.Append(CCFLAGS = Split(lenv['BF_DEBUG_FLAGS']), CXXFLAGS = Split(lenv['BF_DEBUG_FLAGS']))
359             else:
360                     lenv.Append(CCFLAGS = lenv['REL_CFLAGS'], CXXFLAGS = lenv['REL_CCFLAGS'])
361             if lenv['BF_PROFILE']:
362                     lenv.Append(CCFLAGS = Split(lenv['BF_PROFILE_FLAGS']), CXXFLAGS = Split(lenv['BF_PROFILE_FLAGS']))
363             if compileflags:
364                 lenv.Append(CCFLAGS = compileflags)
365                 lenv.Append(CXXFLAGS = compileflags)
366             lenv.Append(CCFLAGS = Split(lenv['C_WARN']))
367             lenv.Append(CXXFLAGS = Split(lenv['CC_WARN']))
368             lib = lenv.Library(target= '#'+root_build_dir+'lib/'+libname, source=sources)
369             SConsEnvironment.Default(self, lib) # we add to default target, because this way we get some kind of progress info during build
370         else:
371             print bc.WARNING+'Not building '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC+' for '+bc.OKBLUE+'BF_QUICK'+bc.ENDC
372         # note: libs is a global
373         add_lib_to_dict(libs, libtype, libname, priority)
374
375     def BlenderProg(self=None, builddir=None, progname=None, sources=None, includes=None, libs=None, libpath=None, binarykind=''):
376         print bc.HEADER+'Configuring program '+bc.ENDC+bc.OKGREEN+progname+bc.ENDC
377         lenv = self.Copy()
378         if lenv['OURPLATFORM'] in ['win32-vc', 'cygwin']:
379             lenv.Append(LINKFLAGS = Split(lenv['PLATFORM_LINKFLAGS']))
380         if  lenv['OURPLATFORM']=='darwin':
381             lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS'])
382             lenv.Append(LINKFLAGS = lenv['BF_PYTHON_LINKFLAGS'])
383             lenv.Append(LINKFLAGS = lenv['BF_OPENGL_LINKFLAGS'])
384         if lenv['BF_PROFILE']:
385                 lenv.Append(LINKFLAGS = lenv['BF_PROFILE_FLAGS'])
386         lenv.Append(CPPPATH=includes)
387         lenv.Append(LIBPATH=libpath)
388         lenv.Append(LIBS=libs)
389         if lenv['WITH_BF_QUICKTIME']:
390              lenv.Append(LIBS = lenv['BF_QUICKTIME_LIB'])
391              lenv.Append(LIBPATH = lenv['BF_QUICKTIME_LIBPATH'])
392         prog = lenv.Program(target=builddir+'bin/'+progname, source=sources)
393         SConsEnvironment.Default(self, prog)
394         program_list.append(prog)
395         if  lenv['OURPLATFORM']=='darwin':
396             lenv['BINARYKIND'] = binarykind
397             lenv.AddPostAction(prog,Action(AppIt,strfunction=my_appit_print))
398
399     def Glob(lenv, pattern):
400         path = string.replace(GetBuildPath(lenv,'SConscript'),'SConscript', '')
401         files = []
402         for i in glob.glob(path + pattern):
403             files.append(string.replace(i, path, ''))
404         return files