################ needed imports
import os
import sys

################ base paths (needed for Win32 OS)
sdlbase = 'D:\\sdl-devel\\SDL'
sdlimagebase = 'D:\\sdl-devel\\SDL_image'
sdlnetbase = 'D:\\sdl-devel\\SDL_net'
sdlmixerbase = 'D:\\sdl-devel\\SDL_mixer'
fftw3base = 'D:\\fftw3'
glbase = 'D:\\Dev-Cpp\\include\\gl'
#sdlbase = os.environ['SDL']
#sdlimagebase = os.environ['SDLIMAGE']
#sdlnetbase = os.environ['SDLNET']
#sdlmixerbase = os.environ['SDLMIXER']
#fftw3base = os.environ['FFTW']
#glbase = os.environ['GLBASE']

################ command line config
debug = int(ARGUMENTS.get('debug', 0))
devel = int(ARGUMENTS.get('devel', 0))
cvedit = int(ARGUMENTS.get('cvedit', 0))
usex86sse = int(ARGUMENTS.get('usex86sse', 0))
useefence = int(ARGUMENTS.get('useefence', 0))
useduma = int(ARGUMENTS.get('useduma', 0))
archflag = ARGUMENTS.get('arch', '')

################ set environment

osspecificsrc = []
extralibs = []

fftwlib = 'fftw3'
if sys.platform == 'win32':
	print "Compiling for Win32 Environment"
	env = Environment(ENV = os.environ, tools = ['mingw'])
	env.Append(CPPPATH = [sdlbase + '\\include', sdlimagebase + '\\include', sdlnetbase + '\\include', sdlmixerbase + '\\include', fftw3base, glbase])
	libpath = [sdlbase + '\\lib', sdlimagebase + '\\lib', sdlnetbase + '\\lib', sdlmixerbase + '\\lib', fftw3base]
	gllibs = ['opengl32', 'glu32']
	sdllibs = ['SDL', 'SDL_image']
	env.Append(CPPDEFINES = ['_REENTRANT'])
	env.Append(CCFLAGS = '-Wall -O2') # for mingw!
	if (usex86sse >= 1):
		osspecificsrc += []
		env.Append(CCFLAGS = '-msse')
		env.Append(CPPDEFINES = ['USE_SSE'])
		print 'Using x86 SSE/MMX optimizations with GCC intrinsics.'
	datadir = './data'	# use slashes as separator always. C/C++ want it so.
	build_dir = 'win32'
elif sys.platform == 'darwin':
	print "Compiling for MacOSX"
	env = Environment(ENV = os.environ)
	env.Append(CPPPATH = ['/System/Library/Frameworks/AGL.framework/Headers', '/System/Library/Frameworks/OpenGL.framework/Headers','/Developer/SDKs/MacOSX10.4u.sdk/usr/X11R6/include' , './Mac'])
	libpath = ['/System/Library/Frameworks/OpenGL.framework/Libraries', '/usr/local/lib', '/usr/lib']
	gllibs = []
	sdllibs = ['SDL', 'SDL_image']
	env.Append(CCFLAGS = '-Wall -g -O2 `sdl-config --cflags`')
	env.Append(LINKFLAGS = '-F/System/Library/Frameworks -framework AGL -framework OpenGL -framework GLUT -framework Cocoa -framework SDL -framework SDL_image -framework SDL_mixer -framework SDL_net')
	datadir = './data'	# use slashes as separator always. C/C++ want it so.
	build_dir = 'macosx'
	osspecificsrc = Split("""Mac/SDLMain.m""")
        if (debug == 1):
                env.Append(CCFLAGS = '-g')
                env.Append(CPPDEFINES = ['DEBUG'])
elif (sys.platform == 'freebsd5') or (sys.platform == 'freebsd6') or (sys.platform == 'freebsd7'):
	print "Compiling for FreeBSD Environment"
	env = Environment(ENV = os.environ)
	LOCALBASE = os.environ['LOCALBASE']
	X11BASE = os.environ['X11BASE']
	SDL_CONFIG = os.environ['SDL_CONFIG']
	env.Replace(CC = os.environ['CC'])
	env.Replace(CXX = os.environ['CXX'])
	env.Append(CPPPATH = [LOCALBASE + '/include', LOCALBASE + '/include/SDL11', X11BASE + '/include', X11BASE + '/include/GL'])
	libpath = [LOCALBASE + '/lib', X11BASE + '/lib'] 
	gllibs = ['GL', 'GLU']
	sdllibs = ['SDL_image']
	extralibs = ['execinfo']
	cpuinfof = os.popen('sysctl -n hw.instruction_sse')
	cpuinfol = cpuinfof.readlines()
	mmxsupported = False
	ssesupported = False
        for i in cpuinfol:
		if i == '1\n':
			mmxsupported = True
			ssesupported = True
		if (usex86sse == 0) and (mmxsupported and ssesupported):
                	usex86sse = 1
	        if usex86sse >= 1:
			env.Append(CCFLAGS = '-msse')
        	        env.Append(CPPDEFINES = ['USE_SSE'])
	                osspecificsrc += []
	                print 'Using x86 SSE/MMX optimizations.'

        env.Replace(CCFLAGS = os.environ['CFLAGS'])
	if (debug == 1):
		env.Append(CCFLAGS = '-g')
		env.Append(CPPDEFINES = ['DEBUG'])
        env.Replace(CXXFLAGS = os.environ['CXXFLAGS'] + ' `' + SDL_CONFIG + ' --cflags`')
        env.Append(LINKFLAGS = '`' + SDL_CONFIG + ' --libs`')
        datadir = '/usr/local/share/dangerdeep'
        build_dir = 'freebsd'
	
        if (os.system('grep glBindProgram ' + X11BASE + '/include/GL/gl*.h > /dev/null') == 0):
                gllibdirs = [X11BASE + '/lib/', '/usr/lib/', LOCALBASE + '/lib/']
                gllibdir = ''
                for i in gllibdirs:
                        if (os.system('test -f '+i+'libGL.so') == 0):
                                gllibdir = i
                                break
                if (gllibdir == ''):
                        print 'ERROR: no libGL.so detected!'
                else:
			print 'Found GL library "'+gllibdir+'libGL.so"'
                if (os.system('grep glBindProgram '+gllibdir+'libGL.so > /dev/null') != 0):
                        print 'GL headers declare glBindProgram, but libGL.so has no such symbol! Ignoring all undefined symbols...'
                        # I'm not sure which option will hopefully fix the problem... so i use both...
                        env.Append(LINKFLAGS = '--unresolved-symbols=ignore-all')
                        env.Append(LINKFLAGS = '-Xlinker --unresolved-symbols -Xlinker ignore-all')

else:
	print "Compiling for Unix/Posix/Linux Environment"
	env = Environment(ENV = os.environ)
	env.Append(CPPPATH = ['/usr/include/SDL', '/usr/include/GL'])
	libpath = ['/usr/X11R6/lib']
	gllibs = ['GL', 'GLU']
	sdllibs = ['SDL', 'SDL_image']
	ccflags = '-Wall `sdl-config --cflags` `pkg-config --cflags x11`'
	env.Append(LINKFLAGS = '`pkg-config --libs-only-L x11`')
	if (debug >= 3):
		ccflags += ' -g -pg -O3'	# profiling
	elif (debug == 2):
		ccflags += ' -g -O0'
		env.Append(CPPDEFINES = ['DEBUG'])
	elif (debug == 1):
		ccflags += ' -g -O1'
		env.Append(CPPDEFINES = ['DEBUG'])
	elif (debug == -1):
		ccflags += ' -g -O3 -march=athlon-xp -mfpmath=sse -mmmx -msse -m3dnow'
	elif (debug == -2):	# special g++4.0+ auto vectorization
		ccflags += ' -g -O3 -march=athlon-xp -mfpmath=sse -mmmx -msse -m3dnow -ftree-vectorize -ftree-vectorizer-verbose=2'
	elif (debug == -3):	# special g++4.0+ auto vectorization
		ccflags += ' -g -O3 -march=athlon64 -mfpmath=sse -mmmx -msse -msse2 -m3dnow -ftree-vectorize -ftree-vectorizer-verbose=2'
	else:
		ccflags += ' -g -O2' # debug symbols will be stripped by the linker for a debian package
	# choose specific architecture if requested
	if archflag != '':
		ccflags += ' -march=' + archflag
		print 'Using architecture: ' + archflag
	if (useefence >= 1):
		extralibs += ['efence']
		print 'Linking to ElectricFence library!'
	elif (useduma >= 1):
		extralibs += ['duma']
		print 'Linking to DUMA (EletricFence successor) library!'
	if (cvedit == 1):
		env.Append(CPPDEFINES = ['CVEDIT'])
	# check for mmx/sse support
	cpuinfof = open('/proc/cpuinfo', 'r')
	cpuinfol = cpuinfof.readlines()
	mmxsupported = False
	ssesupported = False
	for i in cpuinfol:
		if i.startswith('flags'):
			m = Split(i)
			if 'mmx' in m:
				mmxsupported = True
			if 'sse' in m:
				ssesupported = True
	if (usex86sse == 0) and (mmxsupported and ssesupported):
		usex86sse = 1
	if usex86sse >= 1:
		env.Append(CPPDEFINES = ['USE_SSE'])
		env.Append(CCFLAGS = '-msse')
		osspecificsrc += []
		if (usex86sse >= 2):
			env.Append(CPPDEFINES = ['USE_SSE_ALWAYS'])
			print 'Using x86 SSE/MMX optimizations with GCC intrinsics ALWAYS WITHOUT DETECTION!'
		else:
			print 'Using x86 SSE/MMX optimizations with GCC intrinsics.'
	env.Append(CCFLAGS = ccflags)
	datadir = '/usr/local/share/dangerdeep'
	build_dir = 'linux'
	# check for broken libGL, ignore undefined symbols then
	if (os.system('grep glBindProgram /usr/include/GL/gl*.h > /dev/null') == 0):
		gllibdirs = ['/usr/X11R6/lib/', '/usr/lib/', '/usr/local/lib/']
		gllibdir = ''
		for i in gllibdirs:
			if (os.system('test -f '+i+'libGL.so') == 0):
				gllibdir = i
				break
		if (gllibdir == ''):
			print 'ERROR: no libGL.so detected!'
		else:
			print 'Found GL library "'+gllibdir+'libGL.so"'
		if (os.system('grep glBindProgram '+gllibdir+'libGL.so > /dev/null') != 0):
			print 'GL headers declare glBindProgram, but libGL.so has no such symbol! Ignoring all undefined symbols...'
			# I'm not sure which option will hopefully fix the problem... so i use both...
			env.Append(LINKFLAGS = '--unresolved-symbols=ignore-all')
			env.Append(LINKFLAGS = '-Xlinker --unresolved-symbols -Xlinker ignore-all')

###### optionally change install and data dirs
if ARGUMENTS.get('datadir', 0):
	datadir = ARGUMENTS.get('datadir', 0)
installbindir = '/usr/local/bin'
if ARGUMENTS.get('installbindir', 0):
	installbindir = ARGUMENTS.get('installbindir', 0)

print 'Install binary path: ' + installbindir
print 'Using data dir: ' + datadir

target_dir = '#build' + os.sep + build_dir
source_base_dir = 'src'

################ configure
conf = Configure(env)
if (devel == 0):
	if not conf.CheckLibWithHeader('GL', 'gl.h', 'C'):
		print 'GL library must be installed!'
		Exit(1)
	if not conf.CheckLibWithHeader('GLU', 'glu.h', 'C'):
		print 'GLU library must be installed!'
		Exit(1)
	if not conf.CheckLibWithHeader('SDL', 'SDL.h', 'C'):
		print 'SDL library must be installed!'
		Exit(1)
	if not conf.CheckLibWithHeader('SDL_image', 'SDL_image.h', 'C'):
		print 'SDL_image library must be installed!'
		Exit(1)
	if not conf.CheckLibWithHeader('SDL_net', 'SDL_net.h', 'C'):
		print 'SDL_net library is needed for network code!'
		Exit(1)
	if not conf.CheckLibWithHeader('SDL_mixer', 'SDL_mixer.h', 'C'):
		print 'SDL_mixer library is needed for sound support!'
		Exit(1)
	if not conf.CheckLibWithHeader('fftw3', 'fftw3.h', 'C'):
		print 'fftw3 library must be installed!'
		Exit(1)
	if conf.CheckLibWithHeader('fftw3f', 'fftw3.h', 'C'):
		print 'fftw3 library supports float type. Using it...'
		fftwlib = 'fftw3f'
		conf.env.Append(CPPDEFINES = ['WITH_FLOAT_FFTW'])
else:
	fftwlib = 'fftw3f'
	conf.env.Append(CPPDEFINES = ['WITH_FLOAT_FFTW'])	# developers always use float...
env = conf.Finish()

######################### source file lists
gfxlibs = ['oglext'] + gllibs + sdllibs
alllibs = ['dftdmedia', 'tinyxml'] + gfxlibs + ['SDL_mixer', 'SDL_net', fftwlib] + extralibs

################ show some help when running scons -h
Help("""
	Danger from the Deep, SConstruct file help:
	Type 'scons' to build the binary.
	Type 'scons -c' to clean up.
	Type 'scons install' to install the game (as root).
	Type 'scons tarball' to build a tarball of the source (works only with Linux).
	Extra options (add them to command line, like 'scons extraoption=value'):
	'debug=x' to build debug level x, levels: 0: normal, 1: debug, 2: more debug,
		3: profiling, -1: extreme optimizations, -2: even more extreme optim.
	'usex86sse=x' where x < 0: disable them, 0: autodetect, 1: enable them, 2: force usage (no runtime detection).
	'useefence=x' when x > 0 use the Electric Fence library (for debugging)
	'useduma=x' when x > 0 use the Electric Fence successor DUMA (for debugging)
	""")

################ build
libpath = libpath + [target_dir]
env.Append(LIBPATH = libpath)

f = open('version.txt', 'r')
version = f.readlines()[0][:-1]
f.close()

Export('env', 'gfxlibs', 'alllibs', 'installbindir', 'datadir', 'version', 'osspecificsrc')

SConscript(source_base_dir + os.sep + 'SConscript', build_dir = target_dir, duplicate = 0)

BuildDir(target_dir, source_base_dir, duplicate=0)

############### Helper functions
def findCVS(basedir):
	f = open(basedir + os.sep + 'CVS' + os.sep + 'Entries')
	lines = f.readlines()
	mydirs = []
	myfiles = []
	for l in lines:
		if l.startswith('D/'):
			l2 = l[2:]
			i = l2.find('/')
			if i != -1:
				l3 = l2[0:i]
				mydirs += [l3]
		elif l.startswith('/'):
			l2 = l[1:]
			i = l2.find('/')
			if i != -1:
				l3 = l2[0:i]
				myfiles += [basedir + os.sep + l3]
	for d in mydirs:
		nextdir = basedir + os.sep + d
		if os.path.isdir(nextdir):
			myfiles += findCVS(nextdir)
	return myfiles

############### option so that "scons tarball" builds a tarball of source
# tar building works only on linux
if (( build_dir == 'linux' ) or ( build_dir == 'freebsd' )) and (os.path.isdir('./CVS')):
	basetarfilename = 'dangerdeep-' + version
	os.system('rm -rf ' + basetarfilename)
	os.system('ln -s . ' + basetarfilename)
	allcvsfiles = findCVS('.')
	filestopack = []
	for i in allcvsfiles:
		if not(i.endswith('.xcf')) and not(i.startswith('./data/')):
			if not(i.startswith('.' + os.sep + 'build')):
				filestopack += [basetarfilename + os.sep + i]
	env.Append(TARFLAGS = '-zh')
	env.Append(TARSUFFIX = '.gz')
	tgz = env.Tar(basetarfilename + '.tar.gz', filestopack)
	env.Alias('tarball', tgz)

############# eof
