import os
import platform
import shutil
import stat
import sconsconfig
import subprocess
import re
import json
import sys
import getpass
import uuid
import time

envdict = sconsconfig.getMachineSpecificEnvironment();
machineSpecificEnvironment = Environment(**envdict);

rootEnvironment = machineSpecificEnvironment.Clone(
   TI_C28_TOOLS = '$TI_C28_ROOT/bin',
   TI_C28_INCLUDE = '$TI_C28_ROOT/include',
   TI_C28_LIB = '$TI_C28_ROOT/lib',
   
   ALT_OUTPUT_DIRS = '--abs_directory=${TARGET.dir} --asm_directory=${TARGET.dir} --list_directory=${TARGET.dir} --obj_directory=${TARGET.dir} --temp_directory=${TARGET.dir}',
   
   # INCPREFIX controls how CPPPATH translates into _CPPINCFLAGS
   INCPREFIX = '-i',
   CC = '$TI_C28_TOOLS/cl2000',
   CCCOM = '$CC $CFLAGS $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS $ALT_OUTPUT_DIRS $SOURCES',
   CCFLAGS = Split(''),
   OBJSUFFIX = '.obj',
   
   AR = '$TI_C28_TOOLS/ar2000',
   ARCOM = '$AR $ARFLAGS -a $TARGET $SOURCES',
   ARFLAGS = Split(''),
   
   AS = '$TI_C28_TOOLS/cl2000',
   ASCOM = '$AS $ASMFLAGS $SOURCES $ALT_OUTPUT_DIRS',
   ASMFLAGS = Split(''),
   # 28xx code, large memory model

   LINKCOM = '$LINK $LINKFLAGS $LINKCMDFILE ${SOURCES} -o ${TARGET.base}.out -m ${TARGET.base}.map -xml_link_info=${TARGET.base}.xml',
   LINK = '$TI_C28_TOOLS/lnk2000',
   LINKFLAGS = Split(''),
   
   MH = '$TI_C28_TOOLS/hex2000',
   MHCOM = '$MH $MHFLAGS --outfile=${TARGET.base}.hex ${TARGET.base}.out',
   MHFLAGS = Split(''),  

);

def emptyPrint(target, source, env):
	return ""

def makePrinter(context):
	def doPrint(target, source, env):
		print(context)
		return ""
	return doPrint

def makeTargetsPrinter(context):
	def doPrint(target, source, env):
		print(context)
		for t in target:
			print("  "+str(t.rfile()));
		return ""
	return doPrint

def makeSourcePrinter(context):
	def doPrint(target, source, env):
		print(context)
		print("  "+str(source[0].rfile()));
		return ""
	return doPrint
	
def makeStartBuildStepAction(id):
	def action(target, source, env):
		pass
	return Action(action, emptyPrint)

def makeEndBuildStepAction():
	def action(target, source, env):
		pass
	return Action(action, emptyPrint)

class SilentAction:
	def __init__(self, base):
		self.base = base
	def strfunction(self, target, source, env):
#		s = self.base.strfunction(target, source, env)
		return ""
	def __call__(self, *args, **kw):
		return self.base.__call__(*args, **kw)
		
env0 = rootEnvironment.Clone(
   # 994 = missing return value in a non-void-return-value function
   # (default behavior: warning)
   # 179 = function xxx declared but never referenced
   # 225 = disallow use of implicit function declarations
   # 890 = returning reference to local variable
   # 342 = value copied to temporary, reference to temporary used
   # 195 = missing #defines get treated as 0 (default behavior: remark)
   CCFLAGS = Split('--display_error_number --diag_error=994 --diag_error=890 --diag_error=225 --diag_warning=342 --diag_suppress=179 --diag_error=195 --symdebug:dwarf --super_quiet --issue_remarks --verbose_diagnostics --gen_func_subsections --large_memory_model --unified_memory --silicon_version=28 --opt_level=1'),
   LINKFLAGS = Split('-a -qq -c -ecode_start -stack0x200 -w -x --generate_dead_funcs_list=${TARGET.dir}/${TARGET.filebase}.deadfuncs.xml'),   
   ASMFLAGS = Split('-v28 --symdebug:dwarf -qq --large_memory_model'),   
   # 28xx code, large memory model
   MHFLAGS = Split('--romwidth=16 --memwidth=16 --intel -qq'),
);

env0['CXXCOM'] = env0['CCCOM'];

#Same for C++.

includePaths = {'CPPPATH' : [
  '#/src', 
  '#/src/device_drivers',
  '$TI_C28_INCLUDE',
  ]};
env0.MergeFlags(includePaths);

links = {'LINKFLAGS' : [
  '-i$TI_C28_LIB',
#  '-lrts2800_fpu32.lib',
  '-lrts2800_ml.lib',
#  '-lrts2800.lib',
  'DSP2833x_Headers_nonBIOS.cmd'
  ]};
env0.MergeFlags(links);

# Override base builders so they print the way we want.
def overrideBuilder(b, suffix, action_id, action):
	b.add_action(suffix,[
		makeStartBuildStepAction(action_id),
		action,
		makeEndBuildStepAction(),
	]);
	
overrideBuilder(env0['BUILDERS']['Object'], '.c', 'compile-c', Action('$CCCOM',makeTargetsPrinter("compile")));
overrideBuilder(env0['BUILDERS']['Object'], '.cpp', 'compile-cpp', Action('$CXXCOM',makeTargetsPrinter("compile")));
overrideBuilder(env0['BUILDERS']['Object'], '.asm', 'assemble', Action('$ASCOM',makeTargetsPrinter("assemble")));

# custom builder for Gandalf:
# (see Scons manuals:
#  http://www.scons.org/doc/latest/HTML/scons-user/x3621.html
#  http://www.scons.org/doc/latest/HTML/scons-user/c3702.html
#  chdir enters into the target directory; filebase just has the local filename base (no dir path)
# )
#
# 		    'copy ${SOURCE} ${TARGET.dir}/${SOURCE.filebase}',

env0['BUILD_ROOT'] = Dir('.');

def makeAlteredSuffixEmitter(suffixes):
	def emitter(target, source, env):	
		targ0 = target[0].rfile()
		[base,ext] = os.path.splitext(str(target[0]))
		newtargets = [targ0.File(base+s) for s in suffixes]
		result = (newtargets, source+['${BUILD_ROOT.abspath}/$GANDALF'])
		return result
	return emitter
def makeAdditionalDependenciesEmitter(dependencies):
	def emitter(target, source, env):
		deplist = ['${BUILD_ROOT.abspath}/'+d for d in dependencies]
		return (target, source+deplist)
	return emitter

# Links program and runs hex2000.
def DSPProgramGenerator(target, source, env, for_signature):
	return [
		makeStartBuildStepAction('link'),
	    Action('$LINKCOM',makeTargetsPrinter("link")),
	    Action('$MHCOM',makeTargetsPrinter("hex2000")),
		makeEndBuildStepAction(),
		];
env0['BUILDERS']['DSPProgram'] = env0.Builder(generator = DSPProgramGenerator);


def make_read_only(target = None, source = None, env = None):
	for f in source:
		os.chmod(str(f), stat.S_IREAD);

def make_writable(env,dir):
	for root,dirs,files in os.walk(dir, topdown=True):
		for name in files:
			p = root+"/"+name;
			os.chmod(p, stat.S_IWRITE);

env0.AddMethod(make_writable, "MakeWritable");
env0.MakeWritable('build');
env0.MakeWritable('build-lite');

env0['CCFLAGS_OPT'] = Split('-O3');

def setupEnv(env, targ, dependencies, read_only_files):
	print dependencies
	t = env.Alias(targ, dependencies);
	env.AddPostAction(read_only_files, SilentAction(Action(make_read_only,emptyPrint)))


# main targets:
################

vdir='build';
envController = env0.Clone();
envController.Append(CCFLAGS=Split('-d"CONTROLLER_FULL=1" -d"CONTROLLER_LITE=0" -d"CPU_XTAL=30" -d"CPU_MHZ=150" -i'+vdir));
env = envController;
env['EXECUTABLE_NAME'] = 'dpe-modpwr.out';
Export('env');
[executable, objects, generated_source_files] = envController.SConscript(['src/SConscript'],variant_dir=vdir,duplicate=0);
setupEnv(envController, 'controller', executable, generated_source_files);


