Initial commit of cloth modifier from branch rev 13453
[blender.git] / SConstruct
1 #!/usr/bin/env python
2 # $Id$
3 # ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version. The Blender
9 # Foundation also sells licenses for use in proprietary software under
10 # the Blender License.  See http://www.blender.org/BL/ for information
11 # about this.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, write to the Free Software Foundation,
20 # Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21 #
22 # The Original Code is Copyright (C) 2006, Blender Foundation
23 # All rights reserved.
24 #
25 # The Original Code is: all of this file.
26 #
27 # Contributor(s): Nathan Letwory.
28 #
29 # ***** END GPL/BL DUAL LICENSE BLOCK *****
30 #
31 # Main entry-point for the SCons building system
32 # Set up some custom actions and target/argument handling
33 # Then read all SConscripts and build
34
35 import sys
36 import os
37 import os.path
38 import string
39 import shutil
40 import glob
41 import re
42
43 import tools.Blender
44 import tools.btools
45 import tools.bcolors
46
47 BlenderEnvironment = tools.Blender.BlenderEnvironment
48 btools = tools.btools
49 B = tools.Blender
50
51 ### globals ###
52 platform = sys.platform
53 quickie = None
54 quickdebug = None
55 nsis_build = None
56
57 ##### BEGIN SETUP #####
58
59 B.possible_types = ['core', 'common', 'blender', 'intern',
60                     'international', 'game', 'game2',
61                     'player', 'player2', 'system']
62
63 B.binarykind = ['blender' , 'blenderplayer']
64 ##################################
65 # target and argument validation #
66 ##################################
67 # XX cheating for BF_FANCY, we check for BF_FANCY before args are validated
68 use_color = ARGUMENTS.get('BF_FANCY', '1')
69 if platform=='win32':
70     use_color = None
71
72 if not use_color=='1':
73     B.bc.disable()
74     
75  #on defaut white Os X terminal, some colors are totally unlegible
76 if platform=='darwin':
77     B.bc.OKGREEN = '\033[34m'
78     B.bc.WARNING = '\033[36m'
79
80 # arguments
81 print B.bc.HEADER+'Command-line arguments'+B.bc.ENDC
82 B.arguments = btools.validate_arguments(ARGUMENTS, B.bc)
83 btools.print_arguments(B.arguments, B.bc)
84
85 # targets
86 print B.bc.HEADER+'Command-line targets'+B.bc.ENDC
87 B.targets = btools.validate_targets(COMMAND_LINE_TARGETS, B.bc)
88 btools.print_targets(B.targets, B.bc)
89
90 ##########################
91 # setting up environment #
92 ##########################
93
94 # handling cmd line arguments & config file
95
96 # first check cmdline for toolset and we create env to work on
97 quickie = B.arguments.get('BF_QUICK', None)
98 quickdebug = B.arguments.get('BF_QUICKDEBUG', None)
99
100 if quickdebug:
101     B.quickdebug=string.split(quickdebug, ',')
102 else:
103     B.quickdebug=[]
104
105 if quickie:
106     B.quickie=string.split(quickie,',')
107 else:
108     B.quickie=[]
109     
110 toolset = B.arguments.get('BF_TOOLSET', None)
111 if toolset:
112     print "Using " + toolset
113     if toolset=='mstoolkit':
114         env = BlenderEnvironment(ENV = os.environ)
115         env.Tool('mstoolkit', ['tools'])
116     else:
117         env = BlenderEnvironment(tools=[toolset], ENV = os.environ)
118         if env:
119             btools.SetupSpawn(env)
120 else:
121     env = BlenderEnvironment(ENV = os.environ)
122
123 if not env:
124     print "Could not create a build environment"
125     Exit()
126
127
128 cc = B.arguments.get('CC', None)
129 cxx = B.arguments.get('CXX', None)
130 if cc:
131     env['CC'] = cc
132 if cxx:
133     env['CXX'] = cxx
134
135 if env['CC'] in ['cl', 'cl.exe'] and sys.platform=='win32':
136     platform = 'win32-vc'
137 elif env['CC'] in ['gcc'] and sys.platform=='win32':
138     platform = 'win32-mingw'
139
140 env.SConscriptChdir(0)
141
142 crossbuild = B.arguments.get('BF_CROSS', None)
143 if crossbuild and platform!='win32':
144     platform = 'linuxcross'
145
146 env['OURPLATFORM'] = platform
147
148 configfile = B.arguments.get('BF_CONFIG', 'config'+os.sep+platform+'-config.py')
149
150 if os.path.exists(configfile):
151     print B.bc.OKGREEN + "Using config file: " + B.bc.ENDC + configfile
152 else:
153     print B.bc.FAIL + configfile + " doesn't exist" + B.bc.ENDC
154
155 if crossbuild and env['PLATFORM'] != 'win32':
156     print B.bc.HEADER+"Preparing for crossbuild"+B.bc.ENDC
157     env.Tool('crossmingw', ['tools'])
158     # todo: determine proper libs/includes etc.
159     # Needed for gui programs, console programs should do without it
160     env.Append(LINKFLAGS=['-mwindows'])
161
162 # first read platform config. B.arguments will override
163 optfiles = [configfile]
164 if os.path.exists('user-config.py'):
165     print B.bc.OKGREEN + "Using config file: " + B.bc.ENDC + 'user-config.py'
166     optfiles += ['user-config.py']
167 else:
168     print B.bc.WARNING + 'user-config.py' + " not found, no user overrides" + B.bc.ENDC
169
170 opts = btools.read_opts(optfiles, B.arguments)
171 opts.Update(env)
172
173 if not env['BF_FANCY']:
174     B.bc.disable()
175
176 # disable elbeem (fluidsim) compilation?
177 if env['BF_NO_ELBEEM'] == 1:
178     env['CPPFLAGS'].append('-DDISABLE_ELBEEM')
179     env['CXXFLAGS'].append('-DDISABLE_ELBEEM')
180     env['CCFLAGS'].append('-DDISABLE_ELBEEM')
181
182 if env['WITH_BF_OPENMP'] == 1:
183         if env['OURPLATFORM']=='win32-vc':
184                 env.Append(LINKFLAGS=['/openmp'])
185                 env['CCFLAGS'].append('/openmp')
186                 env['CPPFLAGS'].append('/openmp')
187                 env['CXXFLAGS'].append('/openmp')
188         else:
189                 env.Append(LINKFLAGS=['-lgomp'])
190                 env['CCFLAGS'].append('-fopenmp')
191                 env['CPPFLAGS'].append('-fopenmp')
192                 env['CXXFLAGS'].append('-fopenmp')
193
194 #check for additional debug libnames
195
196 if env.has_key('BF_DEBUG_LIBS'):
197     B.quickdebug += env['BF_DEBUG_LIBS']
198
199 printdebug = B.arguments.get('BF_LISTDEBUG', 0)
200
201 # see if this linux distro has libalut
202
203 if env['OURPLATFORM'] == 'linux2' :
204     if env['WITH_BF_OPENAL']:
205         mylib_test_source_file = """
206         #include "AL/alut.h"
207         int main(int argc, char **argv)
208         {
209             alutGetMajorVersion();
210             return 0;
211         }
212         """
213
214         def CheckFreeAlut(context,env):
215             context.Message( B.bc.OKGREEN + "Linux platform detected:\n  checking for FreeAlut... " + B.bc.ENDC )
216             env['LIBS'] = 'alut'
217             result = context.TryLink(mylib_test_source_file, '.c')
218             context.Result(result)
219             return result
220
221         env2 = env.Copy( LIBPATH = env['BF_OPENAL'] ) 
222         conf = Configure( env2, {'CheckFreeAlut' : CheckFreeAlut}, '.sconf_temp', '/dev/null' )
223         if conf.CheckFreeAlut( env2 ):
224             env['BF_OPENAL_LIB'] += ' alut'
225         del env2
226         for root, dirs, files in os.walk('.sconf_temp', topdown=False):
227             for name in files:
228                 os.remove(os.path.join(root, name))
229             for name in dirs:
230                 os.rmdir(os.path.join(root, name))
231         os.rmdir(root)
232
233 if len(B.quickdebug) > 0 and printdebug != 0:
234     print B.bc.OKGREEN + "Buildings these libs with debug symbols:" + B.bc.ENDC
235     for l in B.quickdebug:
236         print "\t" + l
237
238 # check target for blenderplayer. Set WITH_BF_PLAYER if found on cmdline
239 if 'blenderplayer' in B.targets:
240     env['WITH_BF_PLAYER'] = True
241
242 if 'blendernogame' in B.targets:
243     env['WITH_BF_GAMEENGINE'] = False
244
245 # lastly we check for root_build_dir ( we should not do before, otherwise we might do wrong builddir
246 #B.root_build_dir = B.arguments.get('BF_BUILDDIR', '..'+os.sep+'build'+os.sep+platform+os.sep)
247 B.root_build_dir = env['BF_BUILDDIR']
248 env['BUILDDIR'] = B.root_build_dir
249 if not B.root_build_dir[-1]==os.sep:
250     B.root_build_dir += os.sep
251     
252 # We do a shortcut for clean when no quicklist is given: just delete
253 # builddir without reading in SConscripts
254 do_clean = None
255 if 'clean' in B.targets:
256     do_clean = True
257
258 if not quickie and do_clean:
259     if os.path.exists(B.root_build_dir):
260         print B.bc.HEADER+'Cleaning...'+B.bc.ENDC
261         dirs = os.listdir(B.root_build_dir)
262         for dir in dirs:
263             if os.path.isdir(B.root_build_dir + dir) == 1:
264                 print "clean dir %s"%(B.root_build_dir+dir)
265                 shutil.rmtree(B.root_build_dir+dir)
266         print B.bc.OKGREEN+'...done'+B.bc.ENDC
267     else:
268         print B.bc.HEADER+'Already Clean, nothing to do.'+B.bc.ENDC
269     Exit()
270
271 if not os.path.isdir ( B.root_build_dir):
272     os.makedirs ( B.root_build_dir )
273     os.makedirs ( B.root_build_dir + 'source' )
274     os.makedirs ( B.root_build_dir + 'intern' )
275     os.makedirs ( B.root_build_dir + 'extern' )
276     os.makedirs ( B.root_build_dir + 'lib' )
277     os.makedirs ( B.root_build_dir + 'bin' )
278
279 Help(opts.GenerateHelpText(env))
280
281 # default is new quieter output, but if you need to see the 
282 # commands, do 'scons BF_QUIET=0'
283 bf_quietoutput = B.arguments.get('BF_QUIET', '1')
284 if bf_quietoutput=='1':
285     B.set_quiet_output(env)
286 else:
287     if toolset=='msvc':
288         B.msvc_hack(env)
289
290 print B.bc.HEADER+'Building in '+B.bc.ENDC+B.root_build_dir
291 env.SConsignFile(B.root_build_dir+'scons-signatures')
292 B.init_lib_dict()
293
294 ##### END SETUP ##########
295
296 Export('env')
297
298 BuildDir(B.root_build_dir+'/intern', 'intern', duplicate=0)
299 SConscript(B.root_build_dir+'/intern/SConscript')
300 BuildDir(B.root_build_dir+'/extern', 'extern', duplicate=0)
301 SConscript(B.root_build_dir+'/extern/SConscript')
302 BuildDir(B.root_build_dir+'/source', 'source', duplicate=0)
303 SConscript(B.root_build_dir+'/source/SConscript')
304
305 # now that we have read all SConscripts, we know what
306 # libraries will be built. Create list of
307 # libraries to give as objects to linking phase
308 mainlist = []
309 for tp in B.possible_types:
310     if not tp == 'player' and not tp == 'player2':
311         mainlist += B.create_blender_liblist(env, tp)
312
313 if B.arguments.get('BF_PRIORITYLIST', '0')=='1':
314     B.propose_priorities()
315
316 dobj = B.buildinfo(env, "dynamic") + B.resources
317 thestatlibs, thelibincs = B.setup_staticlibs(env)
318 thesyslibs = B.setup_syslibs(env)
319
320 env.BlenderProg(B.root_build_dir, "blender", dobj + mainlist + thestatlibs, [], thesyslibs, [B.root_build_dir+'/lib'] + thelibincs, 'blender')
321 if env['WITH_BF_PLAYER']:
322     playerlist = B.create_blender_liblist(env, 'player')
323     env.BlenderProg(B.root_build_dir, "blenderplayer", dobj + playerlist + thestatlibs, [], thesyslibs, [B.root_build_dir+'/lib'] + thelibincs, 'blenderplayer')
324
325 ##### Now define some targets
326
327
328 #------------ INSTALL
329
330 #-- binaries
331 blenderinstall = []
332 if  env['OURPLATFORM']=='darwin':
333     for prg in B.program_list:
334         bundle = '%s.app' % prg[0]
335         bundledir = os.path.dirname(bundle)
336         for dp, dn, df in os.walk(bundle):
337             if 'CVS' in dn:
338                 dn.remove('CVS')
339             if '.svn' in dn:
340                 dn.remove('.svn')
341             dir=env['BF_INSTALLDIR']+dp[len(bundledir):]
342             source=[dp+os.sep+f for f in df]
343             blenderinstall.append(env.Install(dir=dir,source=source))
344 else:
345     blenderinstall = env.Install(dir=env['BF_INSTALLDIR'], source=B.program_list)
346
347 #-- .blender
348 dotblendlist = []
349 dottargetlist = []
350 for dp, dn, df in os.walk('bin/.blender'):
351     if 'CVS' in dn:
352         dn.remove('CVS')
353     if '.svn' in dn:
354         dn.remove('.svn')
355     for f in df:
356         dotblendlist.append(dp+os.sep+f)
357         dottargetlist.append(env['BF_INSTALLDIR']+dp[3:]+os.sep+f)
358
359 dotblenderinstall = []
360 for targetdir,srcfile in zip(dottargetlist, dotblendlist):
361     td, tf = os.path.split(targetdir)
362     dotblenderinstall.append(env.Install(dir=td, source=srcfile))
363
364 #-- .blender/scripts
365 scriptinstall = []
366 scriptpath='release/scripts'
367 for dp, dn, df in os.walk(scriptpath):
368     if 'CVS' in dn:
369         dn.remove('CVS')
370     if '.svn' in dn:
371         dn.remove('.svn')
372     dir=env['BF_INSTALLDIR']+'/.blender/scripts'+dp[len(scriptpath):]
373     source=[dp+os.sep+f for f in df]
374     scriptinstall.append(env.Install(dir=dir,source=source))
375
376 #-- plugins
377 pluglist = []
378 plugtargetlist = []
379 for tp, tn, tf in os.walk('release/plugins'):
380     if 'CVS' in tn:
381         tn.remove('CVS')
382     if '.svn' in tn:
383         tn.remove('.svn')
384     for f in tf:
385         pluglist.append(tp+os.sep+f)
386         plugtargetlist.append(env['BF_INSTALLDIR']+tp[7:]+os.sep+f)
387
388 plugininstall = []
389 for targetdir,srcfile in zip(plugtargetlist, pluglist):
390     td, tf = os.path.split(targetdir)
391     plugininstall.append(env.Install(dir=td, source=srcfile))
392
393 textlist = []
394 texttargetlist = []
395 for tp, tn, tf in os.walk('release/text'):
396     if 'CVS' in tn:
397         tn.remove('CVS')
398     if '.svn' in tn:
399         tn.remove('.svn')
400     for f in tf:
401         textlist.append(tp+os.sep+f)
402
403 textinstall = env.Install(dir=env['BF_INSTALLDIR'], source=textlist)
404
405 allinstall = [blenderinstall, dotblenderinstall, scriptinstall, plugininstall, textinstall]
406
407 if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw'):
408     dllsources = ['${LCGDIR}/gettext/lib/gnu_gettext.dll',
409                         '${LCGDIR}/png/lib/libpng.dll',
410                         '#release/windows/extra/python25.zip',
411                         '#release/windows/extra/zlib.pyd',
412                         '${LCGDIR}/sdl/lib/SDL.dll',
413                         '${LCGDIR}/zlib/lib/zlib.dll',
414                         '${LCGDIR}/tiff/lib/libtiff.dll']
415     if env['BF_DEBUG']:
416         dllsources.append('${LCGDIR}/python/lib/${BF_PYTHON_LIB}_d.dll')
417     else:
418         dllsources.append('${LCGDIR}/python/lib/${BF_PYTHON_LIB}.dll')
419     if env['OURPLATFORM'] == 'win32-mingw':
420         dllsources += ['${LCGDIR}/pthreads/lib/pthreadGC2.dll']
421     else:
422         dllsources += ['${LCGDIR}/pthreads/lib/pthreadVC2.dll']
423     if env['WITH_BF_ICONV']:
424         dllsources += ['${LCGDIR}/iconv/lib/iconv.dll']
425     if env['WITH_BF_FFMPEG']:
426         dllsources += ['${LCGDIR}/ffmpeg/lib/avcodec-51.dll',
427                         '${LCGDIR}/ffmpeg/lib/avformat-51.dll',
428                         '${LCGDIR}/ffmpeg/lib/avutil-49.dll']
429     windlls = env.Install(dir=env['BF_INSTALLDIR'], source = dllsources)
430     allinstall += windlls
431
432 installtarget = env.Alias('install', allinstall)
433 bininstalltarget = env.Alias('install-bin', blenderinstall)
434
435 nsisaction = env.Action(btools.NSIS_Installer, btools.NSIS_print)
436 nsiscmd = env.Command('nsisinstaller', None, nsisaction)
437 nsisalias = env.Alias('nsis', nsiscmd)
438
439 if env['WITH_BF_PLAYER']:
440     blenderplayer = env.Alias('blenderplayer', B.program_list)
441     Depends(blenderplayer,installtarget)
442
443 if not env['WITH_BF_GAMEENGINE']:
444     blendernogame = env.Alias('blendernogame', B.program_list)
445     Depends(blendernogame,installtarget)
446
447 Depends(nsiscmd, allinstall)
448
449 Default(B.program_list)
450
451 if not env['WITHOUT_BF_INSTALL']:
452         Default(installtarget)
453
454 #------------ RELEASE
455 # TODO: zipup the installation
456
457 #------------ BLENDERPLAYER
458 # TODO: build stubs and link into blenderplayer
459
460 #------------ EPYDOC
461 # TODO: run epydoc
462