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