import os, errno, SCons
from time import gmtime, strftime

#---------------#
# Build Options #
#---------------#
opts = Options('vdrift.conf', ARGUMENTS)
opts.Add('settings', 'Directory under user\'s home dir where settings will be stored', '.vdrift')
opts.Add('destdir', 'Staging area to install VDrift to.  Useful for packagers. ', '')
opts.Add('prefix', 'Path prefix.', '/usr') # Can't be /usr/local, it is HARDCODED in default VDrift.config
opts.Add('datadir', 'Path suffix where where VDrift data will be installed', "share/games/vdrift/data") # in most case this dir doesn't exsist => do not use PathOption (Fails on build)
opts.Add('bindir', 'Path suffix where vdrift binary executable will be installed', "share/games/vdrift/bin")
opts.Add('localedir', 'Path suffix were vdrift locales (.mo files) will be installed', "share/locale")
opts.Add('arch', 'Target architecture to compile vdrift for (x86, p4, axp, a64)', 'x86')
opts.Add(BoolOption('minimal', 'Only install minimal data (3 cars and 2 tracks)', 0))
opts.Add(BoolOption('cache', 'Cache options in vdrift.conf', 1))
opts.Add(BoolOption('release', 'Turn off debug option during build', 0))
opts.Add(BoolOption('old_openal', 'Set this to 1 if your compile fails due to missing alut functions in sound code.', 0))
opts.Add(BoolOption('use_gcc_32', 'Set this to 1 if the game runs fine but the cars bounce around (gcc4 bug).', 0))
opts.Add(BoolOption('use_gcc_33', 'Set this to 1 if the game runs fine but the cars bounce around (gcc4 bug).', 0))
opts.Add(BoolOption('use_gcc_34', 'Set this to 1 if the game runs fine but the cars bounce around (gcc4 bug).', 0))
opts.Add(BoolOption('use_apbuild', 'Set this to 1 if you want to compile with apgcc to create an autopackage', 0))
opts.Add(BoolOption('use_binreloc', 'Set this to 1 if you want to compile with Binary Relocation support', 1))
opts.Add(BoolOption('os_cc', 'Set this to 1 if you want to use the operating system\'s C compiler environment variable.', 0))
opts.Add(BoolOption('os_cxx', 'Set this to 1 if you want to use the operating system\'s C++ compiler environment variable.', 0))
opts.Add(BoolOption('os_cxxflags', 'Set this to 1 if you want to use the operating system\'s C++ compiler flags environment variable.', 0))
opts.Add(BoolOption('NLS', 'Set this to 1 to turn on i18n support', 1))


#--------------------------#
# Create Build Environment #
#--------------------------#
oscmd = os.popen('uname')
osinf = oscmd.readlines()
for i in osinf:
#-------------------------------#
# Section used for FreeBSD port #
#-------------------------------#
	if i == 'FreeBSD\n':
		LOCALBASE = os.environ['LOCALBASE']
		X11BASE = os.environ['X11BASE']

		env = Environment(ENV = os.environ,
			CPPPATH = ['#include',LOCALBASE + '/include', LOCALBASE + '/include/AL',X11BASE + '/include'],
			LIBPATH = ['.', '#lib', LOCALBASE + '/lib', X11BASE + '/lib'],
			LINKFLAGS = ['-pthread','-lintl'],
			options = opts)
         
		check_headers = ['GL/gl.h', 'GL/glu.h', 'SDL/SDL.h', 'SDL/SDL_image.h', 'SDL/SDL_net.h']
         
		env.Replace(CC = os.environ['CC'])
		env.Replace(CXX = os.environ['CXX'])
		env.Append(CXXFLAGS = os.environ['CXXFLAGS'])
#----------------------------------#
# Section used for GNU/Linux build #
#----------------------------------#
	if i == 'Linux\n':
		env = Environment(ENV = os.environ,
			CPPPATH = ['#include'],
			CCFLAGS = ['-Wall', '-Wno-non-virtual-dtor'],
			LIBPATH = ['.', '#lib'],
		        options = opts)
         
		check_headers = ['GL/gl.h', 'GL/glu.h', 'SDL/SDL.h', 'SDL/SDL_image.h', 'SDL/SDL_net.h', 'AL/al.h', 'AL/alc.h', 'AL/alut.h']

#--------------#
# Save Options #
#--------------#
opts.Update(env)

if env['cache']:
    opts.Save('vdrift.conf', env)

#--------------------------------------------#
# distcopy and tarballer functions           #
# by Paul Davis <paul@linuxaudiosystems.com> #
#--------------------------------------------#

def distcopy (target, source, env):
    treedir = str (target[0])

    try:
        os.mkdir (treedir)
    except OSError, (errnum, strerror):
        if errnum != errno.EEXIST:
            print 'mkdir ', treedir, ':', strerror

    cmd = 'tar cf - '
    #
    # we don't know what characters might be in the file names
    # so quote them all before passing them to the shell
    #
    all_files = ([ str(s) for s in source ])
    cmd += " ".join ([ "'%s'" % quoted for quoted in all_files])
    cmd += ' | (cd ' + treedir + ' && tar xf -)'
    p = os.popen (cmd)
    return p.close ();

def tarballer (target, source, env):            
    cmd = 'tar -jcf ' + str (target[0]) +  ' ' + str(source[0])
    #cmd = 'tar -jcf ' + str (target[0]) +  ' ' + str(source[0]) + "  --exclude '*~' "
    print 'running ', cmd, ' ... '
    p = os.popen (cmd)
    return p.close ()

dist_bld = Builder (action = distcopy,
                    target_factory = SCons.Node.FS.default_fs.Entry,
                    source_factory = SCons.Node.FS.default_fs.Entry,
                    multi = 1)

tarball_bld = Builder (action = tarballer,
                       target_factory = SCons.Node.FS.default_fs.Entry,
                       source_factory = SCons.Node.FS.default_fs.Entry)

env.Append (BUILDERS = {'Distribute' : dist_bld})
env.Append (BUILDERS = {'Tarball' : tarball_bld})

#--------------------------------------------------#
# Builder for untarring something into another dir #
#--------------------------------------------------#
def tarcopy(target, source, env):
    cmd = 'tar zxf ' + source + ' -C ' + target
    p = os.popen(cmd)
    return p.close()

copy_tar_dir = Builder (action = tarcopy,
                        target_factory = SCons.Node.FS.default_fs.Entry,
                        source_factory = SCons.Node.FS.default_fs.Entry)

env.Append (BUILDERS = {'TarCopy' : copy_tar_dir})

#------------#
# Build Help #
#------------#
Help("""
Type: 'scons' to compile with the default options.
      'scons arch=axp' to compile for Athlon XP support (other options: a64, p4, x86)
      'scons prefix=/usr/local' to install everything in another prefix.
      'scons destdir=$PWD/tmp' to install to $PWD/tmp staging area.
      'scons datadir= to install data files into an alternate directory'
      'scons bindir=games/bin' to executable into an alternate directory.
      'scons localedir=share/locale' to install translation into an alternate directory.
      'scons release=1' to turn off compiler optimizations and debugging info.
      'scons settings=.VDrift' to change settings directory.
      'scons install' (as root) to install VDrift.
      'scons old_openal=1' to use old OpenAL functions.
      'scons use_gcc_3.2=1' to use g++-3.2 instead of the default.
      'scons use_gcc_3.3=1' to use g++-3.3 instead of the default.
      'scons use_gcc_3.4=1' to use g++-3.4 instead of the default.
      'scons use_apbuild=1' to create an autopackage (building with apbuild)
      'scons use_binreloc=0' to turn off binary relocation support
      'scons os_cc=1' to use the operating system's C compiler environment variable
      'scons os_cxx=1' to use the operating system's C++ compiler environment variable
      'scons os_cxxflags=1' to use the operating system's C++ compiler flags environment variable
      'scons NLS=0' To disable internationalization support (An english-only version will be built)
%s 

Note: The options you enter will be saved in the file vdrift.conf and they will be the defaults whice are used every subsequent time you run scons.""" % opts.GenerateHelpText(env))

#--------------------------#
# Check for Libs & Headers #
#--------------------------#
conf = Configure(env)

check_libs = ['openal']

for lib in check_libs:
    if not conf.CheckLib(lib):
        print 'You do not have the %s library installed. Exiting.' % lib
        Exit(1)

# check for alut, but don't exit if it's not there (unless user wants to use new openal)
# otherwise just note its absence
env['alut_found'] = 1
#if not conf.CheckLib('alut'):
#    env['alut_found'] = 0
#    if not env['old_openal']:
#        print 'If you have the newer version of OpenAL, you also need the OpenAL Utility Toolkit or ALUT library. Get it from http://openal.org/. If you are using an older version of OpenAL, you do not need this because it\'s built in. Try compiling with old_openal=1.'
#	Exit(1)

for header in check_headers:
    if not conf.CheckCXXHeader(header):
        print 'You do not have the %s headers installed. Exiting.' % header
        Exit(1)

#-------------#
# directories #
#-------------#
env['data_directory'] = env['destdir'] + env['prefix'] + '/' + env['datadir']

#--------------#
# i18n support # 
#--------------#

if env['NLS']:
    #print 'Checking for internationalization support ...'
    have_gettext = conf.TryAction(Action('xgettext --version'))
    if not have_gettext[0]:
        print 'This system is not configured for internationalized applications (no xgettext command). An english-only version will be built\n'
        env['NLS'] = 0

    if not conf.CheckCHeader('libintl.h'):
        print 'This system is not configured for internationalized applications (no libintl.h). An english-only ersion will be built\n'
        env['NLS'] = 0

env = conf.Finish()

#---------------#
# Debug/release #
#---------------#
if env['release']:
    # release build, debugging off, optimizations on
    env.Append(CCFLAGS = ['-O2'])
else:
    # debug build, lots of debugging, no optimizations
    env.Append(CCFLAGS = ['-g3'])
    env.Append(CPPDEFINES = [('DEBUG','1')])

#-------------#
# g++ version #
#-------------#
if env['use_gcc_32']:
    # change the compiler version to 3.2 to work around gcc4 bugs
    env.Append(CXX = '-3.2')

if env['use_gcc_33']:
    # change the compiler version to 3.2 to work around gcc4 bugs
    env.Append(CXX = '-3.3')

if env['use_gcc_34']:
    # change the compiler version to 3.4 to work around gcc4 bugs
    env.Append(CXX = '-3.4')

if env['use_apbuild']:
    env['CXX'] = 'apg++'
    env['CC'] = 'apgcc'

if env['use_binreloc']:
    env.Append(CPPDEFINES = 'ENABLE_BINRELOC')

#----------------------#
# OS compiler settings #
#----------------------#
if env['os_cc']:
    env.Replace(CC = os.environ['CC'])

if env['os_cxx']:
    env.Replace(CXX = os.environ['CXX'])

if env['os_cxxflags']:
    env.Append(CXXFLAGS = os.environ['CXXFLAGS'])

#------------------------------------#
# Target architecture to compile for #
#------------------------------------#
#if env['arch'] == 'x86':
#    env.Append(CCFLAGS="-march= -mtune=generic")
if env['arch'] == 'axp':
    env.Append(CCFLAGS="-march=athlon-xp")
elif env['arch'] == 'p4':
    env.Append(CCFLAGS="-march=pentium4")
elif env['arch'] == 'a64':
    env.Append(CCFLAGS="-march=athlon64")

#---------#
# Version #
#---------#
version = strftime("%Y-%m-%d")
env.Append(CPPDEFINES = [('VERSION', '\\"%s\\"' % version)])
#------#
# i18n #
#------#
if env['NLS'] == 1:
    env.Append(CCFLAGS="-DENABLE_NLS")
    env.Append(CCFLAGS="-DPACKAGE=\\\"VDrift\\\"")
    env.Append(CCFLAGS="-DLOCALEDIR=\\\"" + env['prefix'] + "/" + env['localedir'] + "\\\"")
#-----------------#
# Create Archives #
#-----------------#
src_dir_name = 'build/vdrift-%s-src' % version
bin_dir_name = 'build/vdrift-%s-bin' % version
# scons_local_tarball = 'tools/scons-local-0.96.1.tar.gz'

src_dir = env.Distribute(src_dir_name, ['SConstruct'])
bin_dir = env.Distribute(bin_dir_name, ['build/vdrift', 'tools/scripts/vdrift-install.sh'])

# env.TarCopy('build/scons-local/', scons_local_tarball)

src_archive = env.Tarball('%s.tar.bz2' % src_dir_name, src_dir)
bin_archive = env.Tarball('%s.tar.bz2' % bin_dir_name, bin_dir)

#----------------#
# Target Aliases #
#----------------#
env.Alias(target = 'install', source = [env['data_directory'], '$destdir$prefix/$bindir'])
env.Alias(target = 'src-package', source = src_archive)
env.Alias(target = 'bin-package', source = bin_archive)

#----------------#
# Subdirectories #
#----------------#
Export(['env', 'version', 'src_dir', 'bin_dir'])
if 'install' in COMMAND_LINE_TARGETS:
    os.system('mkdir -p ' + env['data_directory'])
    os.system('mkdir -p ' + env['destdir'] + env['prefix'] + '/' + env['bindir'])
    SConscript('data/SConscript')

if 'src-package' in COMMAND_LINE_TARGETS:
    SConscript('po/SConscript')
    SConscript('tools/SConscript')
    #SConscript('data/SConscript')
   
if 'autopackage' in COMMAND_LINE_TARGETS:
    env2 = env.Copy()
    env2['destdir'] = os.environ['PWD'] + '/tmp-vdrift-build'
    os.system('mkdir -p ' + os.environ['PWD'] + '/tmp-vdrift-build/usr/share/games/vdrift/bin')
    os.system('mkdir -p ' + os.environ['PWD'] + '/tmp-vdrift-build/usr/share/games/vdrift/data')
    env2['release'] = 1
    opts.Save('vdrift.conf', env2)
    os.system('makeinstaller tools/autopackage/vdrift.apspec')
    opts.Save('vdrift.conf', env)
    Exit (0)

if env['NLS']:
    SConscript('po/SConscript')

#if env['destdir'] != '':
os.system('mkdir -p ' + env['data_directory'])
os.system('mkdir -p ' + env['destdir'] + env['prefix'] + '/' + env['bindir'])

SConscript('docs/SConscript')
SConscript('include/SConscript')
SConscript('src/SConscript', build_dir='build', duplicate = 0)
