#!/usr/bin/python

EnsureSConsVersion(0, 96, 92)

import os, sys, clam

AddOption(
	"--target", 
	dest="target", nargs=1, type='string', action='store', metavar="TARGET",
	help='Generate binaries for TARGET architecture')

crosscompiling = GetOption('target') and 'mingw' in GetOption("target") or False
isWindowsPlatform = sys.platform=='win32' or crosscompiling
isLinuxPlatform = sys.platform=='linux2' and not crosscompiling
isDarwinPlatform = sys.platform=='darwin'

def die(message) :
	print >> sys.stderr, message
	sys.exit()

def diffList(list1, list2) :
	print list2.__class__.__name__
	if isinstance(list2, list) : return [ item for item in list2 if item not in list1 ]
	return list2

def diffDict(dict1, dict2) :
	return dict((
		(key,value) if key not in dict1.keys() else (key,diffList(dict1[key], value))
		for key, value in dict2.items()
		if value!=dict1.get(key,None)
		and key in "CPPDEFINES LIBS LINKFLAGS CPPPATH CPPFLAGS CFLAGS".split()
		))

Export("clam")
sconfs = dict([
	(os.path.dirname(module), SConscript(module))
	for module in Glob('*/SConscript', strings=True)
	])
modules = clam.sortModules(dict(
	( (name, module.Dependencies) for name, module in sconfs.items() )
	))
print "order:", modules


# Collecting module variables
variables = Variables(".options.cache", ARGUMENTS)

#if sys.platform == "linux2" :
#	variables.Add( BoolVariable( 'crossmingw', '', 'no' ))
variables.AddVariables(
	BoolVariable(
		'verbose',
		help = 'Print build commands instead a short description',
		default=False,
		),
	PathVariable(
		'prefix',
		help = 'Installation prefix',
		default='/usr/local',
		validator=PathVariable.PathAccept,
		),
	BoolVariable( 'release', 'Build CLAM with optimizations and stripping debug symbols', 'no'),
	BoolVariable( 'intel_optimize', 'Build CLAM with newer intel specific optimizations', 'no'),
	BoolVariable( 'double', 'CLAM TData type will be double','no'),
	BoolVariable( 'checks', 'Enable defensive programming checks', 'yes' ),

	BoolVariable( 'verbose', 'Display commands', False),
	BoolVariable( 'release_asserts', 'CLAM asserts will be triggered on release builds', 'no'),
	BoolVariable( 'optimize_and_lose_precision', 'Use tabulated trigonometric functions and the like', 'no' ), 
	BoolVariable( 'force_avoid_configure', 'Avoid configure phase. Useful for Eclipse scons plugin. Enable it only if you know what you are doing', 'no' ),
	('distcc_hosts', 'Defines compiling hosts, if defined enables the distcc compiler', ''),
	)
"""
# clam_core options
variables.AddVariables(
	EnumVariable( 'xmlbackend', 'XML passivation backend', 'xercesc', ('xercesc','xmlpp','both','none')),
	BoolVariable( 'with_ladspa', 'Ladspa plugin support', True),
	)

# clam_processing options
variables.AddVariables(
	BoolVariable( 'with_fftw3', 'Selects whether to use fftw3 or not', True),
	BoolVariable( 'with_nr_fft', 'Selects whether to use Numerical Recipes fft algorithm implementation or not', 'yes'),
	)

	# clam_audioio options
variables.AddVariables(
	BoolVariable( 'with_jack', 'Enables/Disable JACK support', not isWindowsPlatform ),
	BoolVariable( 'with_sndfile', 'Enables PCM files reading and writing', 'yes' ),
	BoolVariable( 'with_oggvorbis', 'Enables ogg/vorbis reading and writing support', 'yes' ),
	BoolVariable( 'with_mad', 'Enables mpeg 1 layer 3 files reading and writing support', 'yes' ),
	BoolVariable( 'with_id3', 'Enables support for accesing ID3 tags on mpeg audio streams', 'yes'),
	BoolVariable( 'with_portaudio', 'Enables audio device I/O using PortAudio', 'yes'),
	BoolVariable( 'with_portmidi', 'Enables MIDI device I/O through portmidi', 'no' ),
	)
if isLinuxPlatform :
	variables.Add( BoolVariable( 'with_alsa', 'Enables PCM and MIDI device I/O through ALSA', 'yes' ) )
elif isDarwinPlatform :
	variables.Add( EnumVariable( 'audio_backend', 'Selects audio PCM i/o library used by CLAM backend', 'rtaudio', ('rtaudio','portaudio') ) )
elif isWindowsPlatform :
	variables.Add( EnumVariable( 'audio_backend', 'Selects audio PCM i/o library used by CLAM backend', 'rtaudio', ('rtaudio','directx','portaudio') ) )
"""
for name, sconf in sconfs.items() :
	variables.AddVariables(*sconf.Variables)


toolChain = 'default'
if sys.platform == "win32": toolChain = 'mingw'
# Setting up common environment
env = Environment(ENV=os.environ, tools=[toolChain], variables=variables)
Help(variables.GenerateHelpText(env))

variables.Save(".options.cache", env)
env.SConsignFile()
# scons optimizations
env.Decider('MD5-timestamp') # do not MD5 if the dates don't differ
env.SetOption('max_drift', 60) # just 60 seconds of clock drift
env.SetOption('implicit_cache', 1)
# TOCHECK: still needed?
#SetupSpawn(env) # to solve long command line problems (in win32)

if crosscompiling :
	env.Tool('crossmingw',toolpath=['../../scons/sconstools'])
env.Tool("install")
env.Tool("pkgconfig", toolpath=["."])
env.Tool("clam", toolpath=["."])

env.moveIntermediateInto("generated")
env.activateColorCommandLine()
if not env['verbose'] :
	env.ClamQuietCompilation()

clone = env.Clone()


configTests = env.PkgConfigConfigureChecks()
for sconf in sconfs.values() :
	configTests.update(sconf.CustomTests())

config = env.Configure()
config.AddTests(configTests)

# Actually configuring
config.CheckPkgConfigProgram() or die(
	"pkg-config is required")
config.CheckPkgConfigProgram(minimum_version="0.22") or die(
	"pkg-config is too old")
config.Finish()

moduleEnv = dict()
for name in modules :
	moduleEnv[name] = env.Clone()
	config = moduleEnv[name].Configure()
	config.AddTests(configTests)
	sconfs[name].Configure(config)
	config.Finish()

#print diffDict(clone.Dictionary(), env.Dictionary() )


installTargets, buildTargets = [list(x) for x in zip(*[list(
	sconf.Targets(moduleEnv[name]))
	for name, sconf in sconfs.items()])]

program = env.Program("myprogram", ["a.cxx"])
buildTargets.append(program)

env.Command("uninstall", [], [
	Delete(file) # fails to delete symlinks http://scons.tigris.org/issues/show_bug.cgi?id=2708
#	Action(
#		"rm -f %s"%file,
#		"== Uninstalling %s"%file
#		)
	for file in FindInstalledFiles()])
Alias("install", installTargets)
Default(buildTargets)



