==SCons==
[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) 2001-2002 by NaN Holding BV.
23 # All rights reserved.
24 #
25 # The Original Code is: none 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
55 ##### BEGIN SETUP #####
56
57 B.possible_types = ['core', 'common', 'blender', 'intern',
58                     'international', 'game', 'game2',
59                     'player', 'player2', 'system']
60
61 B.binarykind = ['blender' , 'blenderplayer']
62 ##################################
63 # target and argument validation #
64 ##################################
65 # XX cheating for BF_FANCY, we check for BF_FANCY before args are validated
66 use_color = ARGUMENTS.get('BF_FANCY', '1')
67 if platform=='win32':
68     use_color = None
69
70 if not use_color=='1':
71     B.bc.disable()
72
73 # arguments
74 print B.bc.HEADER+'Command-line arguments'+B.bc.ENDC
75 B.arguments = btools.validate_arguments(ARGUMENTS, B.bc)
76 btools.print_arguments(B.arguments, B.bc)
77
78 # targets
79 print B.bc.HEADER+'Command-line targets'+B.bc.ENDC
80 B.targets = btools.validate_targets(COMMAND_LINE_TARGETS, B.bc)
81 btools.print_targets(B.targets, B.bc)
82
83 ##########################
84 # setting up environment #
85 ##########################
86
87 # handling cmd line arguments & config file
88
89 # first check cmdline for toolset and we create env to work on
90 quickie = B.arguments.get('BF_QUICK', None)
91 if quickie:
92     B.quickie=string.split(quickie,',')
93 else:
94     B.quickie=[]
95
96 toolset = B.arguments.get('BF_TOOLSET', None)
97 if toolset:
98     print "Using " + toolset
99     if toolset=='mstoolkit':
100         env = BlenderEnvironment(ENV = os.environ)
101         env.Tool('mstoolkit', ['tools'])
102     else:
103         env = BlenderEnvironment(tools=[toolset], ENV = os.environ)
104 else:
105     env = BlenderEnvironment(ENV = os.environ)
106
107 if not env:
108     print "Could not create a build environment"
109     Exit()
110
111 cc = B.arguments.get('CC', None)
112 cxx = B.arguments.get('CXX', None)
113 if cc:
114         env['CC'] = cc
115 if cxx:
116         env['CXX'] = cxx
117
118 if env['CC'] in ['cl', 'cl.exe'] and sys.platform=='win32':
119     platform = 'win32-vc'
120 elif env['CC'] in ['gcc'] and sys.platform=='win32':
121     platform = 'win32-mingw'
122
123 crossbuild = B.arguments.get('BF_CROSS', None)
124 if crossbuild and platform!='win32':
125     platform = 'linuxcross'
126
127 env['OURPLATFORM'] = platform
128
129 configfile = B.arguments.get('BF_CONFIG', 'config'+os.sep+platform+'-config.py')
130
131 if os.path.exists(configfile):
132     print B.bc.OKGREEN + "Using config file: " + B.bc.ENDC + configfile
133 else:
134     print B.bc.FAIL + configfile + " doesn't exist" + B.bc.ENDC
135
136 if crossbuild and env['PLATFORM'] != 'win32':
137     print B.bc.HEADER+"Preparing for crossbuild"+B.bc.ENDC
138     env.Tool('crossmingw', ['tools'])
139     # todo: determine proper libs/includes etc.
140     # Needed for gui programs, console programs should do without it
141     env.Append(LINKFLAGS=['-mwindows'])
142
143 # first read platform config. B.arguments will override
144 optfiles = [configfile]
145 if os.path.exists('user-config.py'):
146     print B.bc.OKGREEN + "Using config file: " + B.bc.ENDC + 'user-config.py'
147     optfiles += ['user-config.py']
148 else:
149     print B.bc.WARNING + 'user-config.py' + " not found, no user overrides" + B.bc.ENDC
150
151 opts = btools.read_opts(optfiles, B.arguments)
152 opts.Update(env)
153
154 # check target for blenderplayer. Set WITH_BF_PLAYER if found on cmdline
155 if 'blenderplayer' in B.targets:
156     env['WITH_BF_PLAYER'] = True
157
158 if 'blendernogame' in B.targets:
159     env['WITH_BF_GAMEENGINE'] = False
160
161 # lastly we check for root_build_dir ( we should not do before, otherwise we might do wrong builddir
162 #B.root_build_dir = B.arguments.get('BF_BUILDDIR', '..'+os.sep+'build'+os.sep+platform+os.sep)
163 B.root_build_dir = env['BF_BUILDDIR']
164 env['BUILDDIR'] = B.root_build_dir
165 if not B.root_build_dir[-1]==os.sep:
166     B.root_build_dir += os.sep
167
168 # We do a shortcut for clean when no quicklist is given: just delete
169 # builddir without reading in SConscripts
170 do_clean = None
171 if 'clean' in B.targets:
172     do_clean = True
173
174 if not quickie and do_clean:
175     print B.bc.HEADER+'Cleaning...'+B.bc.ENDC
176     dirs = os.listdir(B.root_build_dir)
177     for dir in dirs:
178         if os.path.isdir(B.root_build_dir + dir) == 1:
179             print "clean dir %s"%(B.root_build_dir+dir)
180             shutil.rmtree(B.root_build_dir+dir)
181     print B.bc.OKGREEN+'...done'+B.bc.ENDC
182     Exit()
183
184 if not os.path.isdir ( B.root_build_dir):
185     os.makedirs ( B.root_build_dir )
186     os.makedirs ( B.root_build_dir + 'source' )
187     os.makedirs ( B.root_build_dir + 'intern' )
188     os.makedirs ( B.root_build_dir + 'extern' )
189     os.makedirs ( B.root_build_dir + 'lib' )
190     os.makedirs ( B.root_build_dir + 'bin' )
191
192 Help(opts.GenerateHelpText(env))
193
194 # default is new quieter output, but if you need to see the 
195 # commands, do 'scons BF_QUIET=0'
196 bf_quietoutput = B.arguments.get('BF_QUIET', '1')
197 if bf_quietoutput=='1':
198     B.set_quiet_output(env)
199 else:
200     if toolset=='msvc':
201         B.msvc_hack(env)
202
203 print B.bc.HEADER+'Building in '+B.bc.ENDC+B.root_build_dir
204 env.SConsignFile(B.root_build_dir+'scons-signatures')
205 B.init_lib_dict()
206
207 ##### END SETUP ##########
208
209 Export('env')
210 #Export('root_build_dir') # this one is still needed for makesdna
211 ##TODO: improve makesdna usage
212
213 BuildDir(B.root_build_dir+'/intern', 'intern', duplicate=0)
214 SConscript(B.root_build_dir+'/intern/SConscript')
215 BuildDir(B.root_build_dir+'/extern', 'extern', duplicate=0)
216 SConscript(B.root_build_dir+'/extern/SConscript')
217 BuildDir(B.root_build_dir+'/source', 'source', duplicate=0)
218 SConscript(B.root_build_dir+'/source/SConscript')
219
220 # now that we have read all SConscripts, we know what
221 # libraries will be built. Create list of
222 # libraries to give as objects to linking phase
223 mainlist = []
224 for tp in B.possible_types:
225     if not tp == 'player' and not tp == 'player2':
226         mainlist += B.create_blender_liblist(env, tp)
227
228 if B.arguments.get('BF_PRIORITYLIST', '0')=='1':
229     B.propose_priorities()
230
231 dobj = B.buildinfo(env, "dynamic")
232 thestatlibs, thelibincs = B.setup_staticlibs(env)
233 thesyslibs = B.setup_syslibs(env)
234
235 env.BlenderProg(B.root_build_dir, "blender", dobj + mainlist + thestatlibs, [], thesyslibs, [B.root_build_dir+'/lib'] + thelibincs, 'blender')
236 if env['WITH_BF_PLAYER']:
237     playerlist = B.create_blender_liblist(env, 'player')
238     env.BlenderProg(B.root_build_dir, "blenderplayer", dobj + playerlist + thestatlibs, [], thesyslibs, [B.root_build_dir+'/lib'] + thelibincs, 'blenderplayer')
239
240 ##### Now define some targets
241
242
243 #------------ INSTALL
244
245 blenderinstall = env.Install(dir=env['BF_INSTALLDIR'], source=B.program_list)
246
247 #-- .blender
248 dotblendlist = []
249 dottargetlist = []
250 for dp, dn, df in os.walk('bin/.blender'):
251     if 'CVS' in dn:
252         dn.remove('CVS')
253     for f in df:
254         dotblendlist.append(dp+os.sep+f)
255         dottargetlist.append(env['BF_INSTALLDIR']+dp[3:]+os.sep+f)
256
257 dotblenderinstall = []
258 for targetdir,srcfile in zip(dottargetlist, dotblendlist):
259     td, tf = os.path.split(targetdir)
260     dotblenderinstall.append(env.Install(dir=td, source=srcfile))
261
262 #-- .blender/scripts
263 scriptlist = glob.glob('release/scripts/*.py')
264 scriptinstall = env.Install(dir=env['BF_INSTALLDIR']+'/.blender/scripts', source=scriptlist)
265
266 #-- plugins
267 pluglist = []
268 plugtargetlist = []
269 for tp, tn, tf in os.walk('release/plugins'):
270     if 'CVS' in tn:
271         tn.remove('CVS')
272     for f in tf:
273         pluglist.append(tp+os.sep+f)
274         plugtargetlist.append(env['BF_INSTALLDIR']+tp[7:]+os.sep+f)
275
276 plugininstall = []
277 for targetdir,srcfile in zip(plugtargetlist, pluglist):
278     td, tf = os.path.split(targetdir)
279     plugininstall.append(env.Install(dir=td, source=srcfile))
280
281 textlist = []
282 texttargetlist = []
283 for tp, tn, tf in os.walk('release/text'):
284     if 'CVS' in tn:
285         tn.remove('CVS')
286     for f in tf:
287         textlist.append(tp+os.sep+f)
288
289 textinstall = env.Install(dir=env['BF_INSTALLDIR'], source=textlist)
290
291 allinstall = [blenderinstall, dotblenderinstall, scriptinstall, plugininstall, textinstall]
292
293 if env['OURPLATFORM'] == 'win32-vc':
294     windlls = env.Install(dir=env['BF_INSTALLDIR'], source = ['#../lib/windows/gettext/lib/gnu_gettext.dll',
295                         '#../lib/windows/png/lib/libpng.dll',
296                         '#../lib/windows/python/lib/python24.dll',
297                         '#../lib/windows/sdl/lib/SDL.dll',
298                         '#../lib/windows/zlib/lib/zlib.dll'])
299     allinstall += windlls
300
301 installtarget = env.Alias('install', allinstall)
302 bininstalltarget = env.Alias('install-bin', blenderinstall)
303
304 if env['WITH_BF_PLAYER']:
305     blenderplayer = env.Alias('blenderplayer', B.program_list)
306     Depends(blenderplayer,installtarget)
307
308 if not env['WITH_BF_GAMEENGINE']:
309     blendernogame = env.Alias('blendernogame', B.program_list)
310     Depends(blendernogame,installtarget)
311
312
313 Default(B.program_list)
314 Default(installtarget)
315
316 #------------ RELEASE
317 # TODO: zipup the installation
318
319 #------------ BLENDERPLAYER
320 # TODO: build stubs and link into blenderplayer
321
322 #------------ EPYDOC
323 # TODO: run epydoc
324