#   Copyright (c) 2007...2009 Axel Wachtler
#   All rights reserved.
#
#   Redistribution and use in source and binary forms, with or without
#   modification, are permitted provided that the following conditions
#   are met:
#
#   * Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
#   * Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#   * Neither the name of the authors nor the names of its contributors
#     may be used to endorse or promote products derived from this software
#     without specific prior written permission.
#
#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
#   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
#   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
#   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
#   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
#   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
#   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
#   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
#   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
#   POSSIBILITY OF SUCH DAMAGE.

# $Id: SConstruct,v 1.54 2010/01/09 19:54:58 awachtler Exp $

#=== modules ==================================================================
import os, time, sys
sys.path.append("./Tools")
import ds2reg, boardcfg

#=== setup build environment ==================================================
if os.name == 'posix':
    dbgfmt = "stabs"
else:
    dbgfmt = "dwarf-2"

com = Environment (
    tools = ['mingw'],
    CC="avr-gcc",
    DBGFMT=dbgfmt,
    CCFLAGS="-g$DBGFMT -mmcu=$CPU -Wall -Wundef -fshort-enums",
#    ENV = {'PATH' : os.environ['PATH']},
    ENV = os.environ,
    ofname = time.strftime("foo-%Y%m%d"),
    )

RUN_SLOW = ARGUMENTS.get('slow',0)
if not RUN_SLOW:
	com.Decider('MD5-timestamp')
	print "Running with optimization --max-drift=1,--implicit-deps-unchanged, MD5-timestamp and selective rules"

# Template processor for transceiver header files
def create_radio_headerfiles(target, source, env):
    ds2reg.generate_header(str(source[0]),str(target[0]))

# Template Processor for Doxygen Config File
def configure_textfile(target, source, env):
    fin = open(str(source[0]),"r")
    fout = open(str(target[0]),"w")
    parms = env['STRINGPARAM']
    for l in fin.xreadlines():
        l = l.rstrip()
        lo = l % parms
        fout.write(lo+"\n")
    fout.close()
    fin.close()

# Template Processor for Doxygen Config File
def configure_doxyfile(target, source, env):
    fin = open(str(source[0]),"r")
    fout = open(str(target[0]),"w")
    for l in fin.xreadlines():
        l = l.rstrip()
        if "WARN_FORMAT" not in l:
            l = env.subst(l)
        fout.write(l+"\n")
    fout.close()
    fin.close()

com["TARFLAGS"] = '-c -z'
com["TARSUFFIX"] = '.tgz'
com['dir_top'] = com.Dir(".")
com['dir_src_doc'] = com.Dir("./Doc")
com['dir_src_img'] = com.Dir("./Doc/Images")
com['dir_install'] = com.Dir("install")
com['dir_install_doc'] = com.Dir("$dir_install/doc")
com['dir_install_xmpl'] = com.Dir("$dir_install/xmpl")
com['PROGSUFFIX']='.elf'
com["dir_build"] = com.Dir("build")
com.SConsignFile(".scons-signatures")

com["BOARD_CFG_FILE"] = "Src/Lib/Inc/boards/board.cfg"
com["boards"]    = boardcfg.get_boards(com['BOARD_CFG_FILE'])
com["boardopts"] = boardcfg.generate_board_dictionary_expanded(com['boards'])

com['BUILDERS']['RadioHeaderWriter'] = Builder(action = create_radio_headerfiles)
com['BUILDERS']['DoxyfileTransformer'] =  Builder(action = configure_doxyfile)
com['BUILDERS']['TextTransformer'] =  Builder(action = configure_textfile)

avr = com.Clone()

#=== targets ==========================================================

#=== Ugly Optimization ================================================
# Prefiltering of the build rules on for "explicitely wanted" targets,
#
# This reduces the build time, since the dependency tree
# gets much smaller.
#
# For testing, the  command "scons -n  --debug=time stb230"
# detects that nothing is todo.
#
# Unfiltered (old) version:
#   Total build time: 22.301233 seconds
#   Total SConscript file execution time: 18.462105 seconds
# Prefiltered version:
#   Total build time: 5.319315 seconds
#   Total SConscript file execution time: 1.648799 seconds
#========================================================================
current_boards = []
for board in com["boardopts"].keys():
    if board in COMMAND_LINE_TARGETS:
        current_boards.append(board)

if 'all' in COMMAND_LINE_TARGETS or \
   len(COMMAND_LINE_TARGETS) == 0 or \
   RUN_SLOW:
    current_boards = com["boardopts"].keys()

if GetOption('help'):
    current_boards = []

if len(COMMAND_LINE_TARGETS) == 1 and 'doc' in COMMAND_LINE_TARGETS:
	current_boards = []

if "arduino" in COMMAND_LINE_TARGETS:
    current_boards.extend(["wdba1281", "mnb900"])

for board in current_boards:
    avr.SConscript('Src/Lib/SConscript',
                    build_dir = '${dir_build}/%s/lib' % board,
                    exports="avr board",
                    duplicate = 0
                    )

    avr.SConscript('Src/App/SConscript',
                    build_dir = '${dir_build}/%s/app' % board,
                    exports="avr board",
                    duplicate = 0
                    )

    avr.SConscript('Src/Xmpl/SConscript',
                    build_dir = '${dir_build}/%s/xmpl' % board,
                    exports="avr board",
                    duplicate = 0
                    )



#
# Install Example sources
#
xmplsources = []
for xmpl in com.Glob('Src/Xmpl/xmpl*.[hc]'):
    x = avr.Install('$dir_install_xmpl',xmpl)
    xmplsources.append(x)

for board in current_boards:
    avr.Depends(board, xmplsources)

#
# Contributions
#

contr = com.Clone()
contr.SConscript("Contrib/Arduino/SConscript", 
               exports="contr board", duplicate=0)


#
# Documentation targets
#
doc = com.Clone()

doc['dox_version'] = ARGUMENTS.get("version","[%s]" % time.asctime())

doc.SConscript("Doc/SConscript", build_dir='build/doc',
               exports="doc", duplicate=0)

doc.SConscript("Doc/Usr/SConscript.xmpl", build_dir='build/xdoc',
               exports="doc", duplicate=0)

doc.SConscript("Doc/Usr/SConscript", build_dir='build/udoc',
               exports="doc", duplicate=0)

doc.SConscript("Doc/App/SConscript", build_dir='build/adoc',
               exports="doc", duplicate=0)

doc.SConscript("Doc/Dev/SConscript", build_dir='build/ddoc',
               exports="doc", duplicate=0)

doc.SConscript("Doc/Contrib/SConscript", build_dir='build/cdoc',
               exports="doc", duplicate=0)

#=== install ==========================================================
i1 = avr.Install('${dir_install}/inc',
        ["Src/Lib/Inc/board.h",
         "Src/Lib/Inc/transceiver.h",
         "Src/Lib/Inc/const.h",
         "Src/Lib/Inc/radio.h",
         "Src/Lib/Inc/ioutil.h",
         "Src/Lib/Ioutil/uart.h",
         "Src/Lib/Inc/timer.h",
         "Src/Lib/Inc/hif.h",
         "Src/Lib/Inc/acc_mma7455.h"])

boardincludes = Glob("Src/Lib/Inc/boards/*.h")
i2 = avr.Install('${dir_install}/inc/boards/', boardincludes)
i3a = com.RadioHeaderWriter('${dir_install}/inc/at86rf230a.h','Templates/at86rf230a.txt')
i3b = com.RadioHeaderWriter('${dir_install}/inc/at86rf230b.h','Templates/at86rf230b.txt')
i3c = com.RadioHeaderWriter('${dir_install}/inc/at86rf231.h','Templates/at86rf231.txt')
i3d = com.RadioHeaderWriter('${dir_install}/inc/at86rf212.h','Templates/at86rf212.txt')
i3e = com.RadioHeaderWriter('${dir_install}/inc/atmega_rfa1.h','Templates/atmega_rfa1.txt')
i4  = com.RadioHeaderWriter('${dir_install}/inc/mma7455.h','Templates/mma7455.txt')


def write_board_cfg_h(env, target, source):
    boardcfg.write_board_header_file(env['boards'], str(target[0]))

i5  = com.Command("${dir_install}/inc/board_cfg.h",
                  "${BOARD_CFG_FILE}",
                  [write_board_cfg_h])

#=== clean ============================================================
com.Clean("distclean",["$dir_build", "$dir_install"])
com.Clean("clean",["$dir_build"])

#=== aliases ==========================================================
libtargets = map(lambda b: "l%s" % b, com["boards"].keys())
apptargets = map(lambda b: "a%s" % b, com["boards"].keys())
xmpltargets = map(lambda b: "x%s" % b, com["boards"].keys())

for i in com["boardopts"].keys():
    avr.Alias(i, Split("l%s a%s x%s"%(i,i,i)))

avr.Alias('libs', libtargets)
avr.Alias('apps', apptargets)
avr.Alias('xmpli', xmplsources)
avr.Alias('xmpls', xmpltargets + xmplsources)
avr.Alias('all', libtargets +  apptargets + xmpltargets + xmplsources)

com.Alias('ddoc',['install/doc/dev'])
com.Alias('adoc',['install/doc/app'])
com.Alias('udoc',['install/doc/usr'])
com.Alias('cdoc',['install/doc/contrib'])
com.Alias('doc',['install/doc'])

com.Alias('install', [i1, i2, i3a, i3b, i3c, i3d, i3e, i4, i5, com["dir_install"] ])

Default('all')

com.Help("""

Build System for uracoli project

Usage:

    scons              - build all targets
    scons <target>     - build the target
    scons -c           - clean all files
    scons -c distclean - remove all created files and directories
    scons -c clean     - remove build directory (leaving install)
    scons -c <target>  - clean all files for the target

    scons slow=1 to disable all optimizations

A <target> can be:
    all          : libraries and applications for all plattforms
    doc          : documentation
     adoc        :  application guide
     ddoc        :  developers guide
     udoc        :  users guide
    libs         : libraries for all plattforms
    apps         : applications for all plattforms
    xmpls        : small example applications for all plattforms
    <BoardType>  : libraries and applications for specified board type
    l<BoardType> : libraries for specified board type
    a<BoardType> : applications for specified board type
    x<BoardType> : small example applications for specified board type


Special Tagerts:
   arduino       : create an arduino update directory

The follwing <BoardType>s are defined in $BOARD_CFG_FILE:

""" + (boardcfg.show_boards(com["boards"])))
