==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 if env['CC'] in ['cl', 'cl.exe'] and sys.platform=='win32':
112     platform = 'win32-vc'
113 elif env['CC'] in ['gcc'] and sys.platform=='win32':
114     platform = 'win32-mingw'
115
116 crossbuild = B.arguments.get('BF_CROSS', None)
117 if crossbuild and platform!='win32':
118     platform = 'linuxcross'
119
120 env['OURPLATFORM'] = platform
121
122 configfile = B.arguments.get('BF_CONFIG', 'config'+os.sep+platform+'-config.py')
123
124 if os.path.exists(configfile):
125     print B.bc.OKGREEN + "Using config file: " + B.bc.ENDC + configfile
126 else:
127     print B.bc.FAIL + configfile + " doesn't exist" + B.bc.ENDC
128
129 if crossbuild and env['PLATFORM'] != 'win32':
130     print B.bc.HEADER+"Preparing for crossbuild"+B.bc.ENDC
131     env.Tool('crossmingw', ['tools'])
132     # todo: determine proper libs/includes etc.
133     # Needed for gui programs, console programs should do without it
134     env.Append(LINKFLAGS=['-mwindows'])
135
136 # first read platform config. B.arguments will override
137 optfiles = [configfile]
138 if os.path.exists('user-config.py'):
139     print B.bc.OKGREEN + "Using config file: " + B.bc.ENDC + 'user-config.py'
140     optfiles += ['user-config.py']
141 else:
142     print B.bc.WARNING + 'user-config.py' + " not found, no user overrides" + B.bc.ENDC
143
144 opts = btools.read_opts(optfiles, B.arguments)
145 opts.Update(env)
146
147 # check target for blenderplayer. Set WITH_BF_PLAYER if found on cmdline
148 if 'blenderplayer' in B.targets:
149     env['WITH_BF_PLAYER'] = True
150
151 if 'blendernogame' in B.targets:
152     env['WITH_BF_GAMEENGINE'] = False
153
154 # lastly we check for root_build_dir ( we should not do before, otherwise we might do wrong builddir
155 #B.root_build_dir = B.arguments.get('BF_BUILDDIR', '..'+os.sep+'build'+os.sep+platform+os.sep)
156 B.root_build_dir = env['BF_BUILDDIR']
157 env['BUILDDIR'] = B.root_build_dir
158 if not B.root_build_dir[-1]==os.sep:
159     B.root_build_dir += os.sep
160
161 # We do a shortcut for clean when no quicklist is given: just delete
162 # builddir without reading in SConscripts
163 do_clean = None
164 if 'clean' in B.targets:
165     do_clean = True
166
167 if not quickie and do_clean:
168     print B.bc.HEADER+'Cleaning...'+B.bc.ENDC
169     dirs = os.listdir(B.root_build_dir)
170     for dir in dirs:
171         if os.path.isdir(B.root_build_dir + dir) == 1:
172             print "clean dir %s"%(B.root_build_dir+dir)
173             shutil.rmtree(B.root_build_dir+dir)
174     print B.bc.OKGREEN+'...done'+B.bc.ENDC
175     Exit()
176
177 if not os.path.isdir ( B.root_build_dir):
178     os.makedirs ( B.root_build_dir )
179     os.makedirs ( B.root_build_dir + 'source' )
180     os.makedirs ( B.root_build_dir + 'intern' )
181     os.makedirs ( B.root_build_dir + 'extern' )
182     os.makedirs ( B.root_build_dir + 'lib' )
183     os.makedirs ( B.root_build_dir + 'bin' )
184
185 Help(opts.GenerateHelpText(env))
186
187 # default is new quieter output, but if you need to see the 
188 # commands, do 'scons BF_QUIET=0'
189 bf_quietoutput = B.arguments.get('BF_QUIET', '1')
190 if bf_quietoutput=='1':
191     B.set_quiet_output(env)
192 else:
193     if toolset=='msvc':
194         B.msvc_hack(env)
195
196 print B.bc.HEADER+'Building in '+B.bc.ENDC+B.root_build_dir
197 env.SConsignFile(B.root_build_dir+'scons-signatures')
198 B.init_lib_dict()
199
200 ##### END SETUP ##########
201
202 Export('env')
203 #Export('root_build_dir') # this one is still needed for makesdna
204 ##TODO: improve makesdna usage
205
206 BuildDir(B.root_build_dir+'/intern', 'intern', duplicate=0)
207 SConscript(B.root_build_dir+'/intern/SConscript')
208 BuildDir(B.root_build_dir+'/extern', 'extern', duplicate=0)
209 SConscript(B.root_build_dir+'/extern/SConscript')
210 BuildDir(B.root_build_dir+'/source', 'source', duplicate=0)
211 SConscript(B.root_build_dir+'/source/SConscript')
212
213 # now that we have read all SConscripts, we know what
214 # libraries will be built. Create list of
215 # libraries to give as objects to linking phase
216 mainlist = []
217 for tp in B.possible_types:
218     if not tp == 'player' and not tp == 'player2':
219         mainlist += B.create_blender_liblist(env, tp)
220
221 if B.arguments.get('BF_PRIORITYLIST', '0')=='1':
222     B.propose_priorities()
223
224 dobj = B.buildinfo(env, "dynamic")
225 thestatlibs, thelibincs = B.setup_staticlibs(env)
226 thesyslibs = B.setup_syslibs(env)
227
228 env.BlenderProg(B.root_build_dir, "blender", dobj + mainlist + thestatlibs, [], thesyslibs, [B.root_build_dir+'/lib'] + thelibincs, 'blender')
229 if env['WITH_BF_PLAYER']:
230     playerlist = B.create_blender_liblist(env, 'player')
231     env.BlenderProg(B.root_build_dir, "blenderplayer", dobj + playerlist + thestatlibs, [], thesyslibs, [B.root_build_dir+'/lib'] + thelibincs, 'blenderplayer')
232
233 ##### Now define some targets
234
235
236 #------------ INSTALL
237
238 blenderinstall = env.Install(dir=env['BF_INSTALLDIR'], source=B.program_list)
239
240 #-- .blender
241 dotblendlist = []
242 dottargetlist = []
243 for dp, dn, df in os.walk('bin/.blender'):
244     if 'CVS' in dn:
245         dn.remove('CVS')
246     for f in df:
247         dotblendlist.append(dp+os.sep+f)
248         dottargetlist.append(env['BF_INSTALLDIR']+dp[3:]+os.sep+f)
249
250 dotblenderinstall = []
251 for targetdir,srcfile in zip(dottargetlist, dotblendlist):
252     td, tf = os.path.split(targetdir)
253     dotblenderinstall.append(env.Install(dir=td, source=srcfile))
254
255 #-- .blender/scripts
256 scriptlist = glob.glob('release/scripts/*.py')
257 scriptinstall = env.Install(dir=env['BF_INSTALLDIR']+'/.blender/scripts', source=scriptlist)
258
259 #-- plugins
260 pluglist = []
261 plugtargetlist = []
262 for tp, tn, tf in os.walk('release/plugins'):
263     if 'CVS' in tn:
264         tn.remove('CVS')
265     for f in tf:
266         pluglist.append(tp+os.sep+f)
267         plugtargetlist.append(env['BF_INSTALLDIR']+tp[7:]+os.sep+f)
268
269 plugininstall = []
270 for targetdir,srcfile in zip(plugtargetlist, pluglist):
271     td, tf = os.path.split(targetdir)
272     plugininstall.append(env.Install(dir=td, source=srcfile))
273
274 textlist = []
275 texttargetlist = []
276 for tp, tn, tf in os.walk('release/text'):
277     if 'CVS' in tn:
278         tn.remove('CVS')
279     for f in tf:
280         textlist.append(tp+os.sep+f)
281
282 textinstall = env.Install(dir=env['BF_INSTALLDIR'], source=textlist)
283
284 allinstall = [blenderinstall, dotblenderinstall, scriptinstall, plugininstall, textinstall]
285
286 if env['OURPLATFORM'] == 'win32-vc':
287     windlls = env.Install(dir=env['BF_INSTALLDIR'], source = ['#../lib/windows/gettext/lib/gnu_gettext.dll',
288                         '#../lib/windows/png/lib/libpng.dll',
289                         '#../lib/windows/python/lib/python24.dll',
290                         '#../lib/windows/sdl/lib/SDL.dll',
291                         '#../lib/windows/zlib/lib/zlib.dll'])
292     allinstall += windlls
293
294 installtarget = env.Alias('install', allinstall)
295 bininstalltarget = env.Alias('install-bin', blenderinstall)
296
297 if env['WITH_BF_PLAYER']:
298     blenderplayer = env.Alias('blenderplayer', B.program_list)
299
300 if not env['WITH_BF_GAMEENGINE']:
301     blendernogame = env.Alias('blendernogame', B.program_list)
302
303 Default(B.program_list)
304 Default(installtarget)
305
306 #------------ RELEASE
307 # TODO: zipup the installation
308
309 #------------ BLENDERPLAYER
310 # TODO: build stubs and link into blenderplayer
311
312 #------------ EPYDOC
313 # TODO: run epydoc
314