mirror of
https://github.com/dhewm/dhewm3.git
synced 2024-11-30 16:11:11 +00:00
510 lines
14 KiB
Python
510 lines
14 KiB
Python
# -*- mode: python -*-
|
|
# DOOM build script
|
|
# TTimo <ttimo@idsoftware.com>
|
|
# http://scons.sourceforge.net
|
|
|
|
import sys, os, time, commands, re, pickle, StringIO, popen2, commands, pdb, zipfile, string
|
|
import SCons
|
|
|
|
sys.path.append( 'sys/scons' )
|
|
import scons_utils
|
|
|
|
conf_filename='site.conf'
|
|
# choose configuration variables which should be saved between runs
|
|
# ( we handle all those as strings )
|
|
serialized=['CC', 'CXX', 'X86', 'BUILD', 'IDNET_HOST', 'DEDICATED',
|
|
'DEBUG_MEMORY', 'LIBC_MALLOC', 'ID_NOLANADDRESS', 'ID_MCHECK',
|
|
'TARGET_CORE', 'TARGET_GAME', 'TARGET_D3XP', 'TARGET_MONO', 'TARGET_DEMO', 'NOCURL',
|
|
'BUILD_ROOT', 'BUILD_GAMEPAK', 'BASEFLAGS' ]
|
|
|
|
# global build mode ------------------------------
|
|
|
|
g_sdk = not os.path.exists( 'sys/scons/SConscript.core' )
|
|
|
|
# ------------------------------------------------
|
|
|
|
# help -------------------------------------------
|
|
|
|
help_string = """
|
|
Usage: scons [OPTIONS] [TARGET] [CONFIG]
|
|
|
|
[OPTIONS] and [TARGET] are covered in command line options, use scons -H
|
|
|
|
[CONFIG]: KEY="VALUE" [...]
|
|
a number of configuration options saved between runs in the """ + conf_filename + """ file
|
|
erase """ + conf_filename + """ to start with default settings again
|
|
|
|
CC (default gcc)
|
|
CXX (default g++)
|
|
Specify C and C++ compilers (defaults gcc and g++)
|
|
ex: CC="gcc-3.3"
|
|
You can use ccache and distcc, for instance:
|
|
CC="ccache distcc gcc" CXX="ccache distcc g++"
|
|
|
|
BUILD (default debug)
|
|
Use debug-all/debug/release to select build settings
|
|
ex: BUILD="release"
|
|
debug-all: no optimisations, debugging symbols
|
|
debug: -O -g
|
|
release: all optimisations, including CPU target etc.
|
|
|
|
BUILD_ROOT (default 'build')
|
|
change the build root directory
|
|
|
|
TARGET_GAME (default 1)
|
|
Build the base game code
|
|
|
|
TARGET_D3XP (default 1)
|
|
Build the d3xp game code
|
|
|
|
BUILD_GAMEPAK (default 0)
|
|
Build a game pak
|
|
|
|
BASEFLAGS (default '')
|
|
Add compile flags
|
|
|
|
X86 (default 0)
|
|
cross compile for x86 (only applicable on x86_64)
|
|
|
|
NOCONF (default 0, not saved)
|
|
ignore site configuration and use defaults + command line only
|
|
"""
|
|
|
|
if ( not g_sdk ):
|
|
help_string += """
|
|
DEDICATED (default 0)
|
|
Control regular / dedicated type of build:
|
|
0 - client
|
|
1 - dedicated server
|
|
2 - both
|
|
|
|
TARGET_CORE (default 1)
|
|
Build the core
|
|
|
|
TARGET_MONO (default 0)
|
|
Build a monolithic binary
|
|
|
|
TARGET_DEMO (default 0)
|
|
Build demo client ( both a core and game, no mono )
|
|
NOTE: if you *only* want the demo client, set TARGET_CORE and TARGET_GAME to 0
|
|
|
|
IDNET_HOST (default to source hardcoded)
|
|
Override builtin IDNET_HOST with your own settings
|
|
|
|
DEBUG_MEMORY (default 0)
|
|
Enables memory logging to file
|
|
|
|
LIBC_MALLOC (default 1)
|
|
Toggle idHeap memory / libc malloc usage
|
|
When libc malloc is on, memory size statistics are wrong ( no _msize )
|
|
|
|
ID_NOLANADDRESS (default 0)
|
|
Don't recognize any IP as LAN address. This is useful when debugging network
|
|
code where LAN / not LAN influences application behaviour
|
|
|
|
ID_MCHECK (default 2)
|
|
Perform heap consistency checking
|
|
0: on in Debug / off in Release
|
|
1 forces on, 2 forces off
|
|
note that Doom has it's own block allocator/checking
|
|
this should not be considered a replacement, but an additional tool
|
|
|
|
SETUP (default 0, not saved)
|
|
build a setup. implies release build
|
|
|
|
SDK (default 0, not saved)
|
|
build an SDK release
|
|
|
|
NOCURL (default 0)
|
|
set to 1 to disable usage of libcurl and http/ftp downloads feature
|
|
"""
|
|
|
|
Help( help_string )
|
|
|
|
# end help ---------------------------------------
|
|
|
|
# sanity -----------------------------------------
|
|
|
|
EnsureSConsVersion( 0, 96 )
|
|
|
|
# end sanity -------------------------------------
|
|
|
|
# system detection -------------------------------
|
|
|
|
# CPU type
|
|
g_cpu = ''
|
|
|
|
uname = commands.getoutput('uname -m')
|
|
if uname == 'x86_64':
|
|
g_cpu = 'x86_64'
|
|
|
|
if len(g_cpu) < 1:
|
|
exp = re.compile('.*i?86.*')
|
|
if exp.match(uname):
|
|
g_cpu = 'x86'
|
|
|
|
if len(g_cpu) < 1:
|
|
uname = commands.getoutput('uname -p')
|
|
if (uname == 'powerpc'):
|
|
g_cpu = 'ppc'
|
|
|
|
if len(g_cpu) < 1:
|
|
g_cpu = 'cpu'
|
|
|
|
g_os = commands.getoutput('uname -s')
|
|
|
|
# end system detection ---------------------------
|
|
|
|
# default settings -------------------------------
|
|
|
|
CC = 'gcc'
|
|
CXX = 'g++'
|
|
BUILD = 'debug'
|
|
X86 = '0'
|
|
DEDICATED = '0'
|
|
TARGET_CORE = '1'
|
|
TARGET_GAME = '1'
|
|
TARGET_D3XP = '1'
|
|
TARGET_MONO = '0'
|
|
TARGET_DEMO = '0'
|
|
IDNET_HOST = ''
|
|
DEBUG_MEMORY = '0'
|
|
LIBC_MALLOC = '1'
|
|
ID_NOLANADDRESS = '0'
|
|
ID_MCHECK = '2'
|
|
BUILD_ROOT = 'build'
|
|
SETUP = '0'
|
|
SDK = '0'
|
|
NOCONF = '0'
|
|
NOCURL = '0'
|
|
BUILD_GAMEPAK = '0'
|
|
BASEFLAGS = ''
|
|
|
|
# end default settings ---------------------------
|
|
|
|
# site settings ----------------------------------
|
|
|
|
if ( not ARGUMENTS.has_key( 'NOCONF' ) or ARGUMENTS['NOCONF'] != '1' ):
|
|
site_dict = {}
|
|
if (os.path.exists(conf_filename)):
|
|
site_file = open(conf_filename, 'r')
|
|
p = pickle.Unpickler(site_file)
|
|
site_dict = p.load()
|
|
print 'Loading build configuration from ' + conf_filename + ':'
|
|
for k, v in site_dict.items():
|
|
exec_cmd = k + '=\'' + v + '\''
|
|
print ' ' + exec_cmd
|
|
exec(exec_cmd)
|
|
else:
|
|
print 'Site settings ignored'
|
|
|
|
# end site settings ------------------------------
|
|
|
|
# command line settings --------------------------
|
|
|
|
for k in ARGUMENTS.keys():
|
|
exec_cmd = k + '=\'' + ARGUMENTS[k] + '\''
|
|
print 'Command line: ' + exec_cmd
|
|
exec( exec_cmd )
|
|
|
|
# end command line settings ----------------------
|
|
|
|
# save site configuration ----------------------
|
|
|
|
if ( not ARGUMENTS.has_key( 'NOCONF' ) or ARGUMENTS['NOCONF'] != '1' ):
|
|
for k in serialized:
|
|
exec_cmd = 'site_dict[\'' + k + '\'] = ' + k
|
|
exec(exec_cmd)
|
|
|
|
site_file = open(conf_filename, 'w')
|
|
p = pickle.Pickler(site_file)
|
|
p.dump(site_dict)
|
|
site_file.close()
|
|
|
|
# end save site configuration ------------------
|
|
|
|
# configuration rules --------------------------
|
|
|
|
if ( SETUP != '0' ):
|
|
DEDICATED = '2'
|
|
BUILD = 'release'
|
|
|
|
if ( g_sdk or SDK != '0' ):
|
|
TARGET_CORE = '0'
|
|
TARGET_GAME = '1'
|
|
TARGET_D3XP = '1'
|
|
TARGET_MONO = '0'
|
|
TARGET_DEMO = '0'
|
|
|
|
# end configuration rules ----------------------
|
|
|
|
# general configuration, target selection --------
|
|
|
|
# common flags
|
|
# BASE + CORE + OPT for engine
|
|
# BASE + GAME + OPT for game
|
|
# _noopt versions of the environements are built without the OPT
|
|
|
|
BASECPPFLAGS = [ ]
|
|
CORECPPPATH = [ ]
|
|
CORELIBPATH = [ ]
|
|
CORECPPFLAGS = [ ]
|
|
GAMECPPFLAGS = [ ]
|
|
BASELINKFLAGS = [ ]
|
|
CORELINKFLAGS = [ ]
|
|
|
|
# for release build, further optimisations that may not work on all files
|
|
OPTCPPFLAGS = [ ]
|
|
|
|
if (g_cpu == 'x86_64' and X86 == '1'):
|
|
print('cross compiling for x86')
|
|
g_cpu = 'x86'
|
|
BASECPPFLAGS.append('-m32')
|
|
BASELINKFLAGS.append('-m32')
|
|
|
|
g_build = '%s/%s-%s' % (BUILD_ROOT, g_cpu, BUILD)
|
|
|
|
SConsignFile( g_build + '/scons.signatures' )
|
|
|
|
if ( DEBUG_MEMORY != '0' ):
|
|
g_build += '-debugmem'
|
|
|
|
if ( LIBC_MALLOC != '1' ):
|
|
g_build += '-nolibcmalloc'
|
|
|
|
LINK = CXX
|
|
|
|
BASECPPFLAGS.extend( BASEFLAGS.split(' ') )
|
|
BASECPPFLAGS.append( '-pipe' )
|
|
# warn all
|
|
BASECPPFLAGS.append( '-Wall' )
|
|
BASECPPFLAGS.append( '-Wno-unknown-pragmas' )
|
|
# this define is necessary to make sure threading support is enabled in X
|
|
CORECPPFLAGS.append( '-DXTHREADS' )
|
|
|
|
# gcc 4.x option only - only export what we mean to from the game SO
|
|
BASECPPFLAGS.append( '-fvisibility=hidden' )
|
|
|
|
if ( "BSD" in g_os ):
|
|
BASECPPFLAGS.append( '-I/usr/local/include' )
|
|
BASELINKFLAGS.append('-L/usr/local/lib')
|
|
|
|
if ( g_sdk or SDK != '0' ):
|
|
BASECPPFLAGS.append( '-D_D3SDK' )
|
|
|
|
if ( BUILD == 'debug-all' ):
|
|
OPTCPPFLAGS = [ '-g', '-D_DEBUG' ]
|
|
if ( ID_MCHECK == '0' ):
|
|
ID_MCHECK = '1'
|
|
elif ( BUILD == 'debug' ):
|
|
OPTCPPFLAGS = [ '-g', '-O1', '-D_DEBUG' ]
|
|
if ( ID_MCHECK == '0' ):
|
|
ID_MCHECK = '1'
|
|
elif ( BUILD == 'release' ):
|
|
# -fomit-frame-pointer: "-O also turns on -fomit-frame-pointer on machines where doing so does not interfere with debugging."
|
|
# on x86 have to set it explicitely
|
|
# -finline-functions: implicit at -O3
|
|
# -fschedule-insns2: implicit at -O2
|
|
# no-unsafe-math-optimizations: that should be on by default really. hit some wonko bugs in physics code because of that
|
|
OPTCPPFLAGS = [ '-O3', '-ffast-math', '-fno-unsafe-math-optimizations', '-fomit-frame-pointer' ]
|
|
if (g_cpu == 'x86'):
|
|
OPTCPPFLAGS.append('-march=pentium3')
|
|
|
|
if ( ID_MCHECK == '0' ):
|
|
ID_MCHECK = '2'
|
|
else:
|
|
print 'Unknown build configuration ' + BUILD
|
|
sys.exit(0)
|
|
|
|
if ( DEBUG_MEMORY != '0' ):
|
|
BASECPPFLAGS += [ '-DID_DEBUG_MEMORY', '-DID_REDIRECT_NEWDELETE' ]
|
|
|
|
if ( LIBC_MALLOC != '1' ):
|
|
BASECPPFLAGS.append( '-DUSE_LIBC_MALLOC=0' )
|
|
|
|
if ( len( IDNET_HOST ) ):
|
|
CORECPPFLAGS.append( '-DIDNET_HOST=\\"%s\\"' % IDNET_HOST)
|
|
|
|
if ( ID_NOLANADDRESS != '0' ):
|
|
CORECPPFLAGS.append( '-DID_NOLANADDRESS' )
|
|
|
|
if ( ID_MCHECK == '1' ):
|
|
BASECPPFLAGS.append( '-DID_MCHECK' )
|
|
|
|
# TODO fix these warnings
|
|
BASECPPFLAGS.append('-Wno-sign-compare')
|
|
BASECPPFLAGS.append('-Wno-switch')
|
|
BASECPPFLAGS.append('-Wno-format-security')
|
|
|
|
# create the build environements
|
|
g_base_env = Environment( ENV = os.environ, CC = CC, CXX = CXX, LINK = LINK, CPPFLAGS = BASECPPFLAGS, LINKFLAGS = BASELINKFLAGS, CPPPATH = CORECPPPATH, LIBPATH = CORELIBPATH )
|
|
scons_utils.SetupUtils( g_base_env )
|
|
|
|
g_env = g_base_env.Clone()
|
|
|
|
g_env['CPPFLAGS'] += OPTCPPFLAGS
|
|
g_env['CPPFLAGS'] += CORECPPFLAGS
|
|
g_env['LINKFLAGS'] += CORELINKFLAGS
|
|
|
|
g_env_noopt = g_base_env.Clone()
|
|
g_env_noopt['CPPFLAGS'] += CORECPPFLAGS
|
|
|
|
g_game_env = g_base_env.Clone()
|
|
g_game_env['CPPFLAGS'] += OPTCPPFLAGS
|
|
g_game_env['CPPFLAGS'] += GAMECPPFLAGS
|
|
|
|
# maintain this dangerous optimization off at all times
|
|
g_env.Append( CPPFLAGS = '-fno-strict-aliasing' )
|
|
g_env_noopt.Append( CPPFLAGS = '-fno-strict-aliasing' )
|
|
g_game_env.Append( CPPFLAGS = '-fno-strict-aliasing' )
|
|
|
|
# mark the globals
|
|
|
|
local_dedicated = 0
|
|
# 0 for monolithic build
|
|
local_gamedll = 1
|
|
# carry around rather than using .a, avoids binutils bugs
|
|
idlib_objects = []
|
|
game_objects = []
|
|
local_demo = 0
|
|
# curl usage. there is a global toggle flag
|
|
local_curl = 0
|
|
# if idlib should produce PIC objects ( depending on core or game inclusion )
|
|
local_idlibpic = 0
|
|
# switch between base game build and d3xp game build
|
|
local_d3xp = 0
|
|
|
|
GLOBALS = 'g_env g_env_noopt g_game_env g_os g_cpu g_build ID_MCHECK idlib_objects game_objects local_dedicated local_gamedll local_demo local_idlibpic local_curl local_d3xp OPTCPPFLAGS'
|
|
|
|
# end general configuration ----------------------
|
|
|
|
# targets ----------------------------------------
|
|
|
|
Export( 'GLOBALS ' + GLOBALS )
|
|
|
|
doom = None
|
|
doomded = None
|
|
game = None
|
|
doom_mono = None
|
|
doom_demo = None
|
|
game_demo = None
|
|
|
|
# build curl if needed
|
|
if ( NOCURL == '0' and ( TARGET_CORE == '1' or TARGET_MONO == '1' ) ):
|
|
local_curl = 1
|
|
Export( 'GLOBALS ' + GLOBALS )
|
|
|
|
if ( TARGET_CORE == '1' ):
|
|
local_gamedll = 1
|
|
local_demo = 0
|
|
local_idlibpic = 0
|
|
if ( DEDICATED == '0' or DEDICATED == '2' ):
|
|
local_dedicated = 0
|
|
Export( 'GLOBALS ' + GLOBALS )
|
|
|
|
VariantDir( g_build + '/obj-core', '.', duplicate = 0 )
|
|
idlib_objects = SConscript( g_build + '/obj-core/sys/scons/SConscript.idlib' )
|
|
Export( 'GLOBALS ' + GLOBALS ) # update idlib_objects
|
|
doom = SConscript( g_build + '/obj-core/sys/scons/SConscript.core' )
|
|
g_env.Default(doom)
|
|
|
|
if ( DEDICATED == '1' or DEDICATED == '2' ):
|
|
local_dedicated = 1
|
|
Export( 'GLOBALS ' + GLOBALS )
|
|
|
|
VariantDir( g_build + '/dedicated', '.', duplicate = 0 )
|
|
idlib_objects = SConscript( g_build + '/dedicated/sys/scons/SConscript.idlib' )
|
|
Export( 'GLOBALS ' + GLOBALS )
|
|
doomded = SConscript( g_build + '/dedicated/sys/scons/SConscript.core' )
|
|
g_env.Default(doomded)
|
|
|
|
if ( TARGET_GAME == '1' or TARGET_D3XP == '1' ):
|
|
local_gamedll = 1
|
|
local_demo = 0
|
|
local_dedicated = 0
|
|
local_idlibpic = 1
|
|
Export( 'GLOBALS ' + GLOBALS )
|
|
dupe = 0
|
|
if ( SDK == '1' ):
|
|
# building an SDK, use scons for dependencies walking
|
|
# clear the build directory to be safe
|
|
g_env.PreBuildSDK( [ g_build + '/game', g_build + '/d3xp' ] )
|
|
dupe = 1
|
|
VariantDir( g_build + '/obj-base', '.', duplicate = dupe )
|
|
idlib_objects = SConscript( g_build + '/obj-base/sys/scons/SConscript.idlib' )
|
|
if ( TARGET_GAME == '1' ):
|
|
local_d3xp = 0
|
|
Export( 'GLOBALS ' + GLOBALS )
|
|
game = SConscript( g_build + '/obj-base/sys/scons/SConscript.game' )
|
|
g_env.Default(game)
|
|
if ( BUILD_GAMEPAK == '1' ):
|
|
Command( '#game01-base.pk4', [ game, game ], Action( g_env.BuildGamePak ) )
|
|
if ( TARGET_D3XP == '1' ):
|
|
# uses idlib as compiled for game/
|
|
local_d3xp = 1
|
|
VariantDir( g_build + '/obj-d3xp', '.', duplicate = dupe )
|
|
Export( 'GLOBALS ' + GLOBALS )
|
|
d3xp = SConscript( g_build + '/obj-d3xp/sys/scons/SConscript.game' )
|
|
g_env.Default(d3xp)
|
|
if ( BUILD_GAMEPAK == '1' ):
|
|
Command( '#game01-d3xp.pk4', [ d3xp, d3xp ], Action( g_env.BuildGamePak ) )
|
|
|
|
if ( TARGET_MONO == '1' ):
|
|
# NOTE: no D3XP atm. add a TARGET_MONO_D3XP
|
|
local_gamedll = 0
|
|
local_dedicated = 0
|
|
local_demo = 0
|
|
local_idlibpic = 0
|
|
local_d3xp = 0
|
|
Export( 'GLOBALS ' + GLOBALS )
|
|
VariantDir( g_build + '/mono', '.', duplicate = 0 )
|
|
idlib_objects = SConscript( g_build + '/mono/sys/scons/SConscript.idlib' )
|
|
game_objects = SConscript( g_build + '/mono/sys/scons/SConscript.game' )
|
|
Export( 'GLOBALS ' + GLOBALS )
|
|
doom_mono = SConscript( g_build + '/mono/sys/scons/SConscript.core' )
|
|
g_env.Default(doom_mono)
|
|
|
|
if ( TARGET_DEMO == '1' ):
|
|
# NOTE: no D3XP atm. add a TARGET_DEMO_D3XP
|
|
local_demo = 1
|
|
local_dedicated = 0
|
|
local_gamedll = 1
|
|
local_idlibpic = 0
|
|
local_curl = 0
|
|
local_d3xp = 0
|
|
Export( 'GLOBALS ' + GLOBALS )
|
|
VariantDir( g_build + '/demo', '.', duplicate = 0 )
|
|
idlib_objects = SConscript( g_build + '/demo/sys/scons/SConscript.idlib' )
|
|
Export( 'GLOBALS ' + GLOBALS )
|
|
doom_demo = SConscript( g_build + '/demo/sys/scons/SConscript.core' )
|
|
g_env.Default(doom_demo)
|
|
|
|
local_idlibpic = 1
|
|
Export( 'GLOBALS ' + GLOBALS )
|
|
VariantDir( g_build + '/demo/game', '.', duplicate = 0 )
|
|
idlib_objects = SConscript( g_build + '/demo/game/sys/scons/SConscript.idlib' )
|
|
Export( 'GLOBALS ' + GLOBALS )
|
|
game_demo = SConscript( g_build + '/demo/game/sys/scons/SConscript.game' )
|
|
g_env.Default(doom_demo)
|
|
|
|
if ( SETUP != '0' ):
|
|
brandelf = Program( 'brandelf', 'sys/linux/setup/brandelf.c' )
|
|
if ( TARGET_CORE == '1' and TARGET_GAME == '1' and TARGET_D3XP == '1' ):
|
|
setup = Command( 'setup', [ brandelf, doom, doomded, game, d3xp ], Action( g_env.BuildSetup ) )
|
|
else:
|
|
print 'Skipping main setup: TARGET_CORE == 0 or TARGET_GAME == 0'
|
|
if ( TARGET_DEMO == '1' ):
|
|
setup_demo = Command( 'setup-demo', [ brandelf, doom_demo, game_demo ], Action( g_env.BuildSetup ) )
|
|
# if building two setups, make sure JOBS doesn't parallelize them
|
|
try:
|
|
g_env.Depends( setup_demo, setup )
|
|
except:
|
|
pass
|
|
else:
|
|
print 'Skipping demo setup ( TARGET_DEMO == 0 )'
|
|
|
|
if ( SDK != '0' ):
|
|
setup_sdk = Command( 'sdk', [ ], Action( g_env.BuildSDK ) )
|
|
g_env.Depends( setup_sdk, [ game, d3xp ] )
|
|
|
|
# end targets ------------------------------------
|