==Sequencer==
[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 print sys.version_info
44
45 import tools.Blender
46 import tools.btools
47 import tools.bcolors
48
49 BlenderEnvironment = tools.Blender.BlenderEnvironment
50 btools = tools.btools
51 B = tools.Blender
52
53 ### globals ###
54 platform = sys.platform
55 quickie = None
56 quickdebug = None
57
58 ##### BEGIN SETUP #####
59
60 B.possible_types = ['core', 'common', 'blender', 'intern',
61                     'international', 'game', 'game2',
62                     'player', 'player2', 'system']
63
64 B.binarykind = ['blender' , 'blenderplayer']
65 ##################################
66 # target and argument validation #
67 ##################################
68 # XX cheating for BF_FANCY, we check for BF_FANCY before args are validated
69 use_color = ARGUMENTS.get('BF_FANCY', '1')
70 if platform=='win32':
71     use_color = None
72
73 if not use_color=='1':
74     B.bc.disable()
75
76 # arguments
77 print B.bc.HEADER+'Command-line arguments'+B.bc.ENDC
78 B.arguments = btools.validate_arguments(ARGUMENTS, B.bc)
79 btools.print_arguments(B.arguments, B.bc)
80
81 # targets
82 print B.bc.HEADER+'Command-line targets'+B.bc.ENDC
83 B.targets = btools.validate_targets(COMMAND_LINE_TARGETS, B.bc)
84 btools.print_targets(B.targets, B.bc)
85
86 ##########################
87 # setting up environment #
88 ##########################
89
90 # handling cmd line arguments & config file
91
92 # first check cmdline for toolset and we create env to work on
93 quickie = B.arguments.get('BF_QUICK', None)
94 quickdebug = B.arguments.get('BF_QUICKDEBUG', None)
95
96 if quickdebug:
97         B.quickdebug=string.split(quickdebug, ',')
98 else:
99         B.quickdebug=[]
100                 
101 if quickie:
102     B.quickie=string.split(quickie,',')
103 else:
104     B.quickie=[]
105
106 toolset = B.arguments.get('BF_TOOLSET', None)
107 if toolset:
108     print "Using " + toolset
109     if toolset=='mstoolkit':
110         env = BlenderEnvironment(ENV = os.environ)
111         env.Tool('mstoolkit', ['tools'])
112     else:
113         env = BlenderEnvironment(tools=[toolset], ENV = os.environ)
114 else:
115     env = BlenderEnvironment(ENV = os.environ)
116
117 if not env:
118     print "Could not create a build environment"
119     Exit()
120
121 cc = B.arguments.get('CC', None)
122 cxx = B.arguments.get('CXX', None)
123 if cc:
124         env['CC'] = cc
125 if cxx:
126         env['CXX'] = cxx
127
128 if env['CC'] in ['cl', 'cl.exe'] and sys.platform=='win32':
129     platform = 'win32-vc'
130 elif env['CC'] in ['gcc'] and sys.platform=='win32':
131     platform = 'win32-mingw'
132
133 crossbuild = B.arguments.get('BF_CROSS', None)
134 if crossbuild and platform!='win32':
135     platform = 'linuxcross'
136
137 env['OURPLATFORM'] = platform
138
139 configfile = B.arguments.get('BF_CONFIG', 'config'+os.sep+platform+'-config.py')
140
141 if os.path.exists(configfile):
142     print B.bc.OKGREEN + "Using config file: " + B.bc.ENDC + configfile
143 else:
144     print B.bc.FAIL + configfile + " doesn't exist" + B.bc.ENDC
145
146 if crossbuild and env['PLATFORM'] != 'win32':
147     print B.bc.HEADER+"Preparing for crossbuild"+B.bc.ENDC
148     env.Tool('crossmingw', ['tools'])
149     # todo: determine proper libs/includes etc.
150     # Needed for gui programs, console programs should do without it
151     env.Append(LINKFLAGS=['-mwindows'])
152
153 # first read platform config. B.arguments will override
154 optfiles = [configfile]
155 if os.path.exists('user-config.py'):
156     print B.bc.OKGREEN + "Using config file: " + B.bc.ENDC + 'user-config.py'
157     optfiles += ['user-config.py']
158 else:
159     print B.bc.WARNING + 'user-config.py' + " not found, no user overrides" + B.bc.ENDC
160
161 opts = btools.read_opts(optfiles, B.arguments)
162 opts.Update(env)
163
164 #check for additional debug libnames
165
166 if env.has_key('BF_DEBUG_LIBS'):
167         B.quickdebug += env['BF_DEBUG_LIBS']
168
169 printdebug = B.arguments.get('BF_LISTDEBUG', 0)
170
171 # see if this linux distro has libalut
172
173 if env['OURPLATFORM'] == 'linux2' :
174     if env['WITH_BF_OPENAL']:
175         mylib_test_source_file = """
176         #include "AL/alut.h"
177         int main(int argc, char **argv)
178         {
179                 alutGetMajorVersion();
180                 return 0;
181         }
182         """
183
184         def CheckFreeAlut(context,env):
185             context.Message( B.bc.OKGREEN + "Linux platform detected:\n  checking for FreeAlut... " + B.bc.ENDC )
186             env['LIBS'] = 'alut'
187             result = context.TryLink(mylib_test_source_file, '.c')
188             context.Result(result)
189             return result
190
191         env2 = env.Copy( LIBPATH = env['BF_OPENAL'] ) 
192         conf = Configure( env2, {'CheckFreeAlut' : CheckFreeAlut}, '.sconf_temp', '/dev/null' )
193         if conf.CheckFreeAlut( env2 ):
194             env['BF_OPENAL_LIB'] += ' alut'
195         del env2
196         for root, dirs, files in os.walk('.sconf_temp', topdown=False):
197             for name in files:
198                 os.remove(os.path.join(root, name))
199             for name in dirs:
200                 os.rmdir(os.path.join(root, name))
201         os.rmdir(root)
202
203 if len(B.quickdebug) > 0 and printdebug != 0:
204         print B.bc.OKGREEN + "Buildings these libs with debug symbols:" + B.bc.ENDC
205         for l in B.quickdebug:
206                 print "\t" + l
207
208 # check target for blenderplayer. Set WITH_BF_PLAYER if found on cmdline
209 if 'blenderplayer' in B.targets:
210     env['WITH_BF_PLAYER'] = True
211
212 if 'blendernogame' in B.targets:
213     env['WITH_BF_GAMEENGINE'] = False
214
215 # lastly we check for root_build_dir ( we should not do before, otherwise we might do wrong builddir
216 #B.root_build_dir = B.arguments.get('BF_BUILDDIR', '..'+os.sep+'build'+os.sep+platform+os.sep)
217 B.root_build_dir = env['BF_BUILDDIR']
218 env['BUILDDIR'] = B.root_build_dir
219 if not B.root_build_dir[-1]==os.sep:
220     B.root_build_dir += os.sep
221
222 # We do a shortcut for clean when no quicklist is given: just delete
223 # builddir without reading in SConscripts
224 do_clean = None
225 if 'clean' in B.targets:
226     do_clean = True
227
228 if not quickie and do_clean:
229     print B.bc.HEADER+'Cleaning...'+B.bc.ENDC
230     dirs = os.listdir(B.root_build_dir)
231     for dir in dirs:
232         if os.path.isdir(B.root_build_dir + dir) == 1:
233             print "clean dir %s"%(B.root_build_dir+dir)
234             shutil.rmtree(B.root_build_dir+dir)
235     print B.bc.OKGREEN+'...done'+B.bc.ENDC
236     Exit()
237
238 if not os.path.isdir ( B.root_build_dir):
239     os.makedirs ( B.root_build_dir )
240     os.makedirs ( B.root_build_dir + 'source' )
241     os.makedirs ( B.root_build_dir + 'intern' )
242     os.makedirs ( B.root_build_dir + 'extern' )
243     os.makedirs ( B.root_build_dir + 'lib' )
244     os.makedirs ( B.root_build_dir + 'bin' )
245
246 Help(opts.GenerateHelpText(env))
247
248 # default is new quieter output, but if you need to see the 
249 # commands, do 'scons BF_QUIET=0'
250 bf_quietoutput = B.arguments.get('BF_QUIET', '1')
251 if bf_quietoutput=='1':
252     B.set_quiet_output(env)
253 else:
254     if toolset=='msvc':
255         B.msvc_hack(env)
256
257 print B.bc.HEADER+'Building in '+B.bc.ENDC+B.root_build_dir
258 env.SConsignFile(B.root_build_dir+'scons-signatures')
259 B.init_lib_dict()
260
261 ##### END SETUP ##########
262
263 Export('env')
264 #Export('root_build_dir') # this one is still needed for makesdna
265 ##TODO: improve makesdna usage
266
267 BuildDir(B.root_build_dir+'/intern', 'intern', duplicate=0)
268 SConscript(B.root_build_dir+'/intern/SConscript')
269 BuildDir(B.root_build_dir+'/extern', 'extern', duplicate=0)
270 SConscript(B.root_build_dir+'/extern/SConscript')
271 BuildDir(B.root_build_dir+'/source', 'source', duplicate=0)
272 SConscript(B.root_build_dir+'/source/SConscript')
273
274 # now that we have read all SConscripts, we know what
275 # libraries will be built. Create list of
276 # libraries to give as objects to linking phase
277 mainlist = []
278 for tp in B.possible_types:
279     if not tp == 'player' and not tp == 'player2':
280         mainlist += B.create_blender_liblist(env, tp)
281
282 if B.arguments.get('BF_PRIORITYLIST', '0')=='1':
283     B.propose_priorities()
284
285 dobj = B.buildinfo(env, "dynamic") + B.resources
286 thestatlibs, thelibincs = B.setup_staticlibs(env)
287 thesyslibs = B.setup_syslibs(env)
288
289 env.BlenderProg(B.root_build_dir, "blender", dobj + mainlist + thestatlibs, [], thesyslibs, [B.root_build_dir+'/lib'] + thelibincs, 'blender')
290 if env['WITH_BF_PLAYER']:
291     playerlist = B.create_blender_liblist(env, 'player')
292     env.BlenderProg(B.root_build_dir, "blenderplayer", dobj + playerlist + thestatlibs, [], thesyslibs, [B.root_build_dir+'/lib'] + thelibincs, 'blenderplayer')
293
294 ##### Now define some targets
295
296
297 #------------ INSTALL
298
299 blenderinstall = env.Install(dir=env['BF_INSTALLDIR'], source=B.program_list)
300
301 #-- .blender
302 dotblendlist = []
303 dottargetlist = []
304 for dp, dn, df in os.walk('bin/.blender'):
305     if 'CVS' in dn:
306         dn.remove('CVS')
307     for f in df:
308         dotblendlist.append(dp+os.sep+f)
309         dottargetlist.append(env['BF_INSTALLDIR']+dp[3:]+os.sep+f)
310
311 dotblenderinstall = []
312 for targetdir,srcfile in zip(dottargetlist, dotblendlist):
313     td, tf = os.path.split(targetdir)
314     dotblenderinstall.append(env.Install(dir=td, source=srcfile))
315
316 #-- .blender/scripts
317 scriptinstall = []
318 scriptpath='release/scripts'
319 for dp, dn, df in os.walk(scriptpath):
320     if 'CVS' in dn:
321         dn.remove('CVS')
322     dir=env['BF_INSTALLDIR']+'/.blender/scripts'+dp[len(scriptpath):]
323     source=[dp+os.sep+f for f in df]
324     scriptinstall.append(env.Install(dir=dir,source=source))
325
326 #-- plugins
327 pluglist = []
328 plugtargetlist = []
329 for tp, tn, tf in os.walk('release/plugins'):
330     if 'CVS' in tn:
331         tn.remove('CVS')
332     for f in tf:
333         pluglist.append(tp+os.sep+f)
334         plugtargetlist.append(env['BF_INSTALLDIR']+tp[7:]+os.sep+f)
335
336 plugininstall = []
337 for targetdir,srcfile in zip(plugtargetlist, pluglist):
338     td, tf = os.path.split(targetdir)
339     plugininstall.append(env.Install(dir=td, source=srcfile))
340
341 textlist = []
342 texttargetlist = []
343 for tp, tn, tf in os.walk('release/text'):
344     if 'CVS' in tn:
345         tn.remove('CVS')
346     for f in tf:
347         textlist.append(tp+os.sep+f)
348
349 textinstall = env.Install(dir=env['BF_INSTALLDIR'], source=textlist)
350
351 allinstall = [blenderinstall, dotblenderinstall, scriptinstall, plugininstall, textinstall]
352
353 if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw'):
354     dllsources = ['#../lib/windows/gettext/lib/gnu_gettext.dll',
355                         '#../lib/windows/png/lib/libpng.dll',
356                         '#../lib/windows/python/lib/python24.dll',
357                         '#../lib/windows/sdl/lib/SDL.dll',
358                         '#../lib/windows/zlib/lib/zlib.dll']
359     if env['OURPLATFORM'] == 'win32-mingw':
360         dllsources += ['#../lib/windows/pthreads/lib/pthreadGC2.dll']
361     else:
362         dllsources += ['#../lib/windows/pthreads/lib/pthreadVC2.dll']
363     windlls = env.Install(dir=env['BF_INSTALLDIR'], source = dllsources)
364     allinstall += windlls
365
366 installtarget = env.Alias('install', allinstall)
367 bininstalltarget = env.Alias('install-bin', blenderinstall)
368
369 if env['WITH_BF_PLAYER']:
370     blenderplayer = env.Alias('blenderplayer', B.program_list)
371     Depends(blenderplayer,installtarget)
372
373 if not env['WITH_BF_GAMEENGINE']:
374     blendernogame = env.Alias('blendernogame', B.program_list)
375     Depends(blendernogame,installtarget)
376
377
378 Default(B.program_list)
379 Default(installtarget)
380
381 #------------ RELEASE
382 # TODO: zipup the installation
383
384 #------------ BLENDERPLAYER
385 # TODO: build stubs and link into blenderplayer
386
387 #------------ EPYDOC
388 # TODO: run epydoc
389