]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/SConstruct
hello world
[icculus/iodoom3.git] / neo / SConstruct
1 # -*- mode: python -*-
2 # DOOM build script
3 # TTimo <ttimo@idsoftware.com>
4 # http://scons.sourceforge.net
5
6 import sys, os, time, commands, re, pickle, StringIO, popen2, commands, pdb, zipfile, string
7 import SCons
8
9 sys.path.append( 'sys/scons' )
10 import scons_utils
11
12 conf_filename='site.conf'
13 # choose configuration variables which should be saved between runs
14 # ( we handle all those as strings )
15 serialized=['CC', 'CXX', 'JOBS', 'BUILD', 'IDNET_HOST', 'GL_HARDLINK', 'DEDICATED',
16         'DEBUG_MEMORY', 'LIBC_MALLOC', 'ID_NOLANADDRESS', 'ID_MCHECK', 'ALSA',
17         'TARGET_CORE', 'TARGET_GAME', 'TARGET_D3XP', 'TARGET_MONO', 'TARGET_DEMO', 'NOCURL',
18         'BUILD_ROOT', 'BUILD_GAMEPAK', 'BASEFLAGS', 'SILENT' ]
19
20 # global build mode ------------------------------
21
22 g_sdk = not os.path.exists( 'sys/scons/SConscript.core' )
23
24 # ------------------------------------------------
25
26 # help -------------------------------------------
27
28 help_string = """
29 Usage: scons [OPTIONS] [TARGET] [CONFIG]
30
31 [OPTIONS] and [TARGET] are covered in command line options, use scons -H
32
33 [CONFIG]: KEY="VALUE" [...]
34 a number of configuration options saved between runs in the """ + conf_filename + """ file
35 erase """ + conf_filename + """ to start with default settings again
36
37 CC (default gcc)
38 CXX (default g++)
39         Specify C and C++ compilers (defaults gcc and g++)
40         ex: CC="gcc-3.3"
41         You can use ccache and distcc, for instance:
42         CC="ccache distcc gcc" CXX="ccache distcc g++"
43
44 JOBS (default 1)
45         Parallel build
46
47 BUILD (default debug)
48         Use debug-all/debug/release to select build settings
49         ex: BUILD="release"
50         debug-all: no optimisations, debugging symbols
51         debug: -O -g
52         release: all optimisations, including CPU target etc.
53
54 BUILD_ROOT (default 'build')
55         change the build root directory
56
57 TARGET_GAME (default 1)
58         Build the base game code
59
60 TARGET_D3XP (default 1)
61         Build the d3xp game code
62
63 BUILD_GAMEPAK (default 0)
64         Build a game pak
65
66 BASEFLAGS (default '')
67         Add compile flags
68
69 NOCONF (default 0, not saved)
70         ignore site configuration and use defaults + command line only
71         
72 SILENT ( default 0, saved )
73         hide the compiler output, unless error
74 """
75
76 if ( not g_sdk ):
77         help_string += """
78 DEDICATED (default 0)
79         Control regular / dedicated type of build:
80         0 - client
81         1 - dedicated server
82         2 - both
83
84 TARGET_CORE (default 1)
85         Build the core
86
87 TARGET_MONO (default 0)
88         Build a monolithic binary
89
90 TARGET_DEMO (default 0)
91         Build demo client ( both a core and game, no mono )
92         NOTE: if you *only* want the demo client, set TARGET_CORE and TARGET_GAME to 0
93
94 IDNET_HOST (default to source hardcoded)
95         Override builtin IDNET_HOST with your own settings
96         
97 GL_HARDLINK (default 0)
98         Instead of dynamically loading the OpenGL libraries, use implicit dependencies
99         NOTE: no GL logging capability and no r_glDriver with GL_HARDLINK 1
100
101 DEBUG_MEMORY (default 0)
102         Enables memory logging to file
103         
104 LIBC_MALLOC (default 1)
105         Toggle idHeap memory / libc malloc usage
106         When libc malloc is on, memory size statistics are wrong ( no _msize )
107
108 ID_NOLANADDRESS (default 0)
109         Don't recognize any IP as LAN address. This is useful when debugging network
110         code where LAN / not LAN influences application behaviour
111         
112 ID_MCHECK (default 2)
113         Perform heap consistency checking
114         0: on in Debug / off in Release
115         1 forces on, 2 forces off
116         note that Doom has it's own block allocator/checking
117         this should not be considered a replacement, but an additional tool
118
119 ALSA (default 1)
120         enable ALSA sound backend support
121         
122 SETUP (default 0, not saved)
123     build a setup. implies release build
124
125 SDK (default 0, not saved)
126         build an SDK release
127
128 NOCURL (default 0)
129         set to 1 to disable usage of libcurl and http/ftp downloads feature
130 """
131
132 Help( help_string )
133
134 # end help ---------------------------------------
135
136 # sanity -----------------------------------------
137
138 EnsureSConsVersion( 0, 96 )
139
140 # end sanity -------------------------------------
141
142 # system detection -------------------------------
143
144 # CPU type
145 cpu = commands.getoutput('uname -m')
146 exp = re.compile('.*i?86.*')
147 if exp.match(cpu):
148         cpu = 'x86'
149 else:
150         cpu = commands.getoutput('uname -p')
151         if ( cpu == 'powerpc' ):
152                 cpu = 'ppc'
153         else:
154                 cpu = 'cpu'
155 g_os = 'Linux'
156
157 # end system detection ---------------------------
158
159 # default settings -------------------------------
160
161 CC = 'gcc'
162 CXX = 'g++'
163 JOBS = '1'
164 BUILD = 'debug'
165 DEDICATED = '0'
166 TARGET_CORE = '1'
167 TARGET_GAME = '1'
168 TARGET_D3XP = '1'
169 TARGET_MONO = '0'
170 TARGET_DEMO = '0'
171 IDNET_HOST = ''
172 GL_HARDLINK = '0'
173 DEBUG_MEMORY = '0'
174 LIBC_MALLOC = '1'
175 ID_NOLANADDRESS = '0'
176 ID_MCHECK = '2'
177 BUILD_ROOT = 'build'
178 ALSA = '1'
179 SETUP = '0'
180 SDK = '0'
181 NOCONF = '0'
182 NOCURL = '0'
183 BUILD_GAMEPAK = '0'
184 BASEFLAGS = ''
185 SILENT = '0'
186
187 # end default settings ---------------------------
188
189 # site settings ----------------------------------
190
191 if ( not ARGUMENTS.has_key( 'NOCONF' ) or ARGUMENTS['NOCONF'] != '1' ):
192         site_dict = {}
193         if (os.path.exists(conf_filename)):
194                 site_file = open(conf_filename, 'r')
195                 p = pickle.Unpickler(site_file)
196                 site_dict = p.load()
197                 print 'Loading build configuration from ' + conf_filename + ':'
198                 for k, v in site_dict.items():
199                         exec_cmd = k + '=\'' + v + '\''
200                         print '  ' + exec_cmd
201                         exec(exec_cmd)
202 else:
203         print 'Site settings ignored'
204
205 # end site settings ------------------------------
206
207 # command line settings --------------------------
208
209 for k in ARGUMENTS.keys():
210         exec_cmd = k + '=\'' + ARGUMENTS[k] + '\''
211         print 'Command line: ' + exec_cmd
212         exec( exec_cmd )
213
214 # end command line settings ----------------------
215
216 # save site configuration ----------------------
217
218 if ( not ARGUMENTS.has_key( 'NOCONF' ) or ARGUMENTS['NOCONF'] != '1' ):
219         for k in serialized:
220                 exec_cmd = 'site_dict[\'' + k + '\'] = ' + k
221                 exec(exec_cmd)
222
223         site_file = open(conf_filename, 'w')
224         p = pickle.Pickler(site_file)
225         p.dump(site_dict)
226         site_file.close()
227
228 # end save site configuration ------------------
229
230 # configuration rules --------------------------
231
232 if ( SETUP != '0' ):
233         DEDICATED       = '2'
234         BUILD           = 'release'
235
236 if ( g_sdk or SDK != '0' ):
237         TARGET_CORE = '0'
238         TARGET_GAME = '1'
239         TARGET_D3XP = '1'
240         TARGET_MONO = '0'
241         TARGET_DEMO = '0'
242
243 # end configuration rules ----------------------
244
245 # general configuration, target selection --------
246
247 g_build = BUILD_ROOT + '/' + BUILD
248
249 SConsignFile( 'scons.signatures' )
250
251 if ( GL_HARDLINK != '0' ):
252         g_build += '-hardlink'
253
254 if ( DEBUG_MEMORY != '0' ):
255         g_build += '-debugmem'
256         
257 if ( LIBC_MALLOC != '1' ):
258         g_build += '-nolibcmalloc'
259
260 SetOption('num_jobs', JOBS)
261
262 LINK = CXX
263
264 # common flags
265 # BASE + CORE + OPT for engine
266 # BASE + GAME + OPT for game
267 # _noopt versions of the environements are built without the OPT
268
269 BASECPPFLAGS = [ ]
270 CORECPPPATH = [ ]
271 CORELIBPATH = [ ]
272 CORECPPFLAGS = [ ]
273 GAMECPPFLAGS = [ ]
274 BASELINKFLAGS = [ ]
275 CORELINKFLAGS = [ ]
276
277 # for release build, further optimisations that may not work on all files
278 OPTCPPFLAGS = [ ]
279
280 BASECPPFLAGS.append( BASEFLAGS )
281 BASECPPFLAGS.append( '-pipe' )
282 # warn all
283 BASECPPFLAGS.append( '-Wall' )
284 BASECPPFLAGS.append( '-Wno-unknown-pragmas' )
285 # this define is necessary to make sure threading support is enabled in X
286 CORECPPFLAGS.append( '-DXTHREADS' )
287 # don't wrap gcc messages
288 BASECPPFLAGS.append( '-fmessage-length=0' )
289 # gcc 4.0
290 BASECPPFLAGS.append( '-fpermissive' )
291
292 if ( g_os == 'Linux' ):
293         # gcc 4.x option only - only export what we mean to from the game SO
294         BASECPPFLAGS.append( '-fvisibility=hidden' )
295         # get the 64 bits machine on the distcc array to produce 32 bit binaries :)
296         BASECPPFLAGS.append( '-m32' )
297         BASELINKFLAGS.append( '-m32' )
298
299 if ( g_sdk or SDK != '0' ):
300         BASECPPFLAGS.append( '-D_D3SDK' )
301
302 if ( BUILD == 'debug-all' ):
303         OPTCPPFLAGS = [ '-g', '-D_DEBUG' ]
304         if ( ID_MCHECK == '0' ):
305                 ID_MCHECK = '1'
306 elif ( BUILD == 'debug' ):
307         OPTCPPFLAGS = [ '-g', '-O1', '-D_DEBUG' ]
308         if ( ID_MCHECK == '0' ):
309                 ID_MCHECK = '1'
310 elif ( BUILD == 'release' ):
311         # -fomit-frame-pointer: "-O also turns on -fomit-frame-pointer on machines where doing so does not interfere with debugging."
312         #   on x86 have to set it explicitely
313         # -finline-functions: implicit at -O3
314         # -fschedule-insns2: implicit at -O2
315         # no-unsafe-math-optimizations: that should be on by default really. hit some wonko bugs in physics code because of that
316         OPTCPPFLAGS = [ '-O3', '-march=pentium3', '-Winline', '-ffast-math', '-fno-unsafe-math-optimizations', '-fomit-frame-pointer' ]
317         if ( ID_MCHECK == '0' ):
318                 ID_MCHECK = '2'
319 else:
320         print 'Unknown build configuration ' + BUILD
321         sys.exit(0)
322
323 if ( GL_HARDLINK != '0' ):
324         CORECPPFLAGS.append( '-DID_GL_HARDLINK' )
325
326 if ( DEBUG_MEMORY != '0' ):
327         BASECPPFLAGS += [ '-DID_DEBUG_MEMORY', '-DID_REDIRECT_NEWDELETE' ]
328         
329 if ( LIBC_MALLOC != '1' ):
330         BASECPPFLAGS.append( '-DUSE_LIBC_MALLOC=0' )
331
332 if ( len( IDNET_HOST ) ):
333         CORECPPFLAGS.append( '-DIDNET_HOST=\\"%s\\"' % IDNET_HOST)
334
335 if ( ID_NOLANADDRESS != '0' ):
336         CORECPPFLAGS.append( '-DID_NOLANADDRESS' )
337         
338 if ( ID_MCHECK == '1' ):
339         BASECPPFLAGS.append( '-DID_MCHECK' )
340         
341 # create the build environements
342 g_base_env = Environment( ENV = os.environ, CC = CC, CXX = CXX, LINK = LINK, CPPFLAGS = BASECPPFLAGS, LINKFLAGS = BASELINKFLAGS, CPPPATH = CORECPPPATH, LIBPATH = CORELIBPATH )
343 scons_utils.SetupUtils( g_base_env )
344
345 g_env = g_base_env.Clone()
346
347 g_env['CPPFLAGS'] += OPTCPPFLAGS
348 g_env['CPPFLAGS'] += CORECPPFLAGS
349 g_env['LINKFLAGS'] += CORELINKFLAGS
350
351 g_env_noopt = g_base_env.Clone()
352 g_env_noopt['CPPFLAGS'] += CORECPPFLAGS
353
354 g_game_env = g_base_env.Clone()
355 g_game_env['CPPFLAGS'] += OPTCPPFLAGS
356 g_game_env['CPPFLAGS'] += GAMECPPFLAGS
357
358 # maintain this dangerous optimization off at all times
359 g_env.Append( CPPFLAGS = '-fno-strict-aliasing' )
360 g_env_noopt.Append( CPPFLAGS = '-fno-strict-aliasing' )
361 g_game_env.Append( CPPFLAGS = '-fno-strict-aliasing' )
362
363 if ( int(JOBS) > 1 ):
364         print 'Using buffered process output'
365         silent = False
366         if ( SILENT == '1' ):
367                 silent = True
368         scons_utils.SetupBufferedOutput( g_env, silent )
369         scons_utils.SetupBufferedOutput( g_game_env, silent )
370
371 # mark the globals
372
373 local_dedicated = 0
374 # 0 for monolithic build
375 local_gamedll = 1
376 # carry around rather than using .a, avoids binutils bugs
377 idlib_objects = []
378 game_objects = []
379 local_demo = 0
380 # curl usage. there is a global toggle flag
381 local_curl = 0
382 curl_lib = []
383 # if idlib should produce PIC objects ( depending on core or game inclusion )
384 local_idlibpic = 0
385 # switch between base game build and d3xp game build
386 local_d3xp = 0
387
388 GLOBALS = 'g_env g_env_noopt g_game_env g_os ID_MCHECK ALSA idlib_objects game_objects local_dedicated local_gamedll local_demo local_idlibpic curl_lib local_curl local_d3xp OPTCPPFLAGS'
389
390 # end general configuration ----------------------
391
392 # targets ----------------------------------------
393
394 Export( 'GLOBALS ' + GLOBALS )
395
396 doom = None
397 doomded = None
398 game = None
399 doom_mono = None
400 doom_demo = None
401 game_demo = None
402
403 # build curl if needed
404 if ( NOCURL == '0' and ( TARGET_CORE == '1' or TARGET_MONO == '1' ) ):
405         # 1: debug, 2: release
406         if ( BUILD == 'release' ):
407                 local_curl = 2
408         else:
409                 local_curl = 1
410         Export( 'GLOBALS ' + GLOBALS )
411         curl_lib = SConscript( 'sys/scons/SConscript.curl' )
412
413 if ( TARGET_CORE == '1' ):
414         local_gamedll = 1
415         local_demo = 0
416         local_idlibpic = 0
417         if ( DEDICATED == '0' or DEDICATED == '2' ):
418                 local_dedicated = 0
419                 Export( 'GLOBALS ' + GLOBALS )
420                 
421                 VariantDir( g_build + '/core/glimp', '.', duplicate = 1 )
422                 SConscript( g_build + '/core/glimp/sys/scons/SConscript.gl' )
423                 VariantDir( g_build + '/core', '.', duplicate = 0 )
424                 idlib_objects = SConscript( g_build + '/core/sys/scons/SConscript.idlib' )
425                 Export( 'GLOBALS ' + GLOBALS ) # update idlib_objects
426                 doom = SConscript( g_build + '/core/sys/scons/SConscript.core' )
427
428                 InstallAs( '#doom.' + cpu, doom )
429                 
430         if ( DEDICATED == '1' or DEDICATED == '2' ):
431                 local_dedicated = 1
432                 Export( 'GLOBALS ' + GLOBALS )
433                 
434                 VariantDir( g_build + '/dedicated/glimp', '.', duplicate = 1 )
435                 SConscript( g_build + '/dedicated/glimp/sys/scons/SConscript.gl' )
436                 VariantDir( g_build + '/dedicated', '.', duplicate = 0 )
437                 idlib_objects = SConscript( g_build + '/dedicated/sys/scons/SConscript.idlib' )
438                 Export( 'GLOBALS ' + GLOBALS )
439                 doomded = SConscript( g_build + '/dedicated/sys/scons/SConscript.core' )
440
441                 InstallAs( '#doomded.' + cpu, doomded )
442
443 if ( TARGET_GAME == '1' or TARGET_D3XP == '1' ):
444         local_gamedll = 1
445         local_demo = 0
446         local_dedicated = 0
447         local_idlibpic = 1
448         Export( 'GLOBALS ' + GLOBALS )
449         dupe = 0
450         if ( SDK == '1' ):
451                 # building an SDK, use scons for dependencies walking
452                 # clear the build directory to be safe
453                 g_env.PreBuildSDK( [ g_build + '/game', g_build + '/d3xp' ] )
454                 dupe = 1
455         VariantDir( g_build + '/game', '.', duplicate = dupe )
456         idlib_objects = SConscript( g_build + '/game/sys/scons/SConscript.idlib' )
457         if ( TARGET_GAME == '1' ):
458                 local_d3xp = 0
459                 Export( 'GLOBALS ' + GLOBALS )
460                 game = SConscript( g_build + '/game/sys/scons/SConscript.game' )
461                 game_base = InstallAs( '#game%s-base.so' % cpu, game )
462                 if ( BUILD_GAMEPAK == '1' ):
463                         Command( '#game01-base.pk4', [ game_base, game ], Action( g_env.BuildGamePak ) )
464         if ( TARGET_D3XP == '1' ):
465                 # uses idlib as compiled for game/
466                 local_d3xp = 1
467                 VariantDir( g_build + '/d3xp', '.', duplicate = dupe )
468                 Export( 'GLOBALS ' + GLOBALS )
469                 d3xp = SConscript( g_build + '/d3xp/sys/scons/SConscript.game' )
470                 game_d3xp = InstallAs( '#game%s-d3xp.so' % cpu, d3xp )
471                 if ( BUILD_GAMEPAK == '1' ):
472                         Command( '#game01-d3xp.pk4', [ game_d3xp, d3xp ], Action( g_env.BuildGamePak ) )
473         
474 if ( TARGET_MONO == '1' ):
475         # NOTE: no D3XP atm. add a TARGET_MONO_D3XP
476         local_gamedll = 0
477         local_dedicated = 0
478         local_demo = 0
479         local_idlibpic = 0
480         local_d3xp = 0
481         Export( 'GLOBALS ' + GLOBALS )
482         VariantDir( g_build + '/mono/glimp', '.', duplicate = 1 )
483         SConscript( g_build + '/mono/glimp/sys/scons/SConscript.gl' )
484         VariantDir( g_build + '/mono', '.', duplicate = 0 )
485         idlib_objects = SConscript( g_build + '/mono/sys/scons/SConscript.idlib' )
486         game_objects = SConscript( g_build + '/mono/sys/scons/SConscript.game' )
487         Export( 'GLOBALS ' + GLOBALS )
488         doom_mono = SConscript( g_build + '/mono/sys/scons/SConscript.core' )
489         InstallAs( '#doom-mon.' + cpu, doom_mono )
490
491 if ( TARGET_DEMO == '1' ):
492         # NOTE: no D3XP atm. add a TARGET_DEMO_D3XP
493         local_demo = 1
494         local_dedicated = 0
495         local_gamedll = 1
496         local_idlibpic = 0
497         local_curl = 0
498         local_d3xp = 0
499         curl_lib = []
500         Export( 'GLOBALS ' + GLOBALS )
501         VariantDir( g_build + '/demo/glimp', '.', duplicate = 1 )
502         SConscript( g_build + '/demo/glimp/sys/scons/SConscript.gl' )
503         VariantDir( g_build + '/demo', '.', duplicate = 0 )
504         idlib_objects = SConscript( g_build + '/demo/sys/scons/SConscript.idlib' )
505         Export( 'GLOBALS ' + GLOBALS )
506         doom_demo = SConscript( g_build + '/demo/sys/scons/SConscript.core' )
507
508         InstallAs( '#doom-demo.' + cpu, doom_demo )
509         
510         local_idlibpic = 1
511         Export( 'GLOBALS ' + GLOBALS )
512         VariantDir( g_build + '/demo/game', '.', duplicate = 0 )
513         idlib_objects = SConscript( g_build + '/demo/game/sys/scons/SConscript.idlib' )
514         Export( 'GLOBALS ' + GLOBALS )
515         game_demo = SConscript( g_build + '/demo/game/sys/scons/SConscript.game' )
516
517         InstallAs( '#game%s-demo.so' % cpu, game_demo )
518
519 if ( SETUP != '0' ):
520         brandelf = Program( 'brandelf', 'sys/linux/setup/brandelf.c' )
521         if ( TARGET_CORE == '1' and TARGET_GAME == '1' and TARGET_D3XP == '1' ):
522                 setup = Command( 'setup', [ brandelf, doom, doomded, game, d3xp ], Action( g_env.BuildSetup ) )
523         else:
524                 print 'Skipping main setup: TARGET_CORE == 0 or TARGET_GAME == 0'
525         if ( TARGET_DEMO == '1' ):
526                 setup_demo = Command( 'setup-demo', [ brandelf, doom_demo, game_demo ], Action( g_env.BuildSetup ) )
527                 # if building two setups, make sure JOBS doesn't parallelize them
528                 try:
529                         g_env.Depends( setup_demo, setup )
530                 except:
531                         pass
532         else:
533                 print 'Skipping demo setup ( TARGET_DEMO == 0 )'
534
535 if ( SDK != '0' ):
536         setup_sdk = Command( 'sdk', [ ], Action( g_env.BuildSDK ) )
537         g_env.Depends( setup_sdk, [ game, d3xp ] )
538
539 # end targets ------------------------------------