Help('''
Type 'scons' to build and run all the available test cases.
It will automatically detect your platform and C compiler and
build appropriately.

You can modify the behavious using following options:
CC          Name of C compiler
CXX         Name of C++ compiler
CCFLAGS     Flags to pass to the C compiler
CXXFLAGS    Flags to pass to the C++ compiler
LINKFLAGS   Flags to pass to linker
PROTOC      Path to protoc binary
PROTOCFLAGS Arguments to pass protoc

For example, for a clang build, use:
scons CC=clang CXX=clang++
''')

import os
env = Environment(ENV = os.environ, tools = ['default', 'nanopb'])

if ARGUMENTS.get('PLATFORM') == 'STM32':
    set_stm32_platform(env)
elif ARGUMENTS.get('PLATFORM') == 'AVR':
    set_avr_platform(env)

# Limit memory usage. This is to catch problems like issue #338
try:
    import resource
    soft, hard = resource.getrlimit(resourse.RLIMIT_AS)
    resource.setrlimit(resource.RLIMIT_AS, (100*1024*1024, hard))
except:
    pass

# Allow overriding the compiler with scons CC=???
if 'CC' in ARGUMENTS: env.Replace(CC = ARGUMENTS['CC'])
if 'CXX' in ARGUMENTS: env.Replace(CXX = ARGUMENTS['CXX'])
if 'CCFLAGS' in ARGUMENTS: env.Append(CCFLAGS = ARGUMENTS['CCFLAGS'])
if 'CXXFLAGS' in ARGUMENTS: env.Append(CXXFLAGS = ARGUMENTS['CXXFLAGS'])
if 'LINKFLAGS' in ARGUMENTS: env.Append(LINKFLAGS = ARGUMENTS['LINKFLAGS'])
if 'PROTOC' in ARGUMENTS: env.Replace(PROTOC = ARGUMENTS['PROTOC'])
if 'PROTOCFLAGS' in ARGUMENTS: env.Replace(PROTOCFLAGS = ARGUMENTS['PROTOCFLAGS'])

# Add the builders defined in site_init.py
add_nanopb_builders(env)

# Path to the files shared by tests, and to the nanopb core.
env.Append(CPPPATH = ["#../", "$COMMON"])

# Path for finding nanopb.proto
env.Append(PROTOCPATH = '#../generator')

# Check the compilation environment, unless we are just cleaning up.
if not env.GetOption('clean'):
    def check_ccflags(context, flags, linkflags = ''):
        '''Check if given CCFLAGS are supported'''
        context.Message('Checking support for CCFLAGS="%s"... ' % flags)
        oldflags = context.env['CCFLAGS']
        oldlinkflags = context.env['LINKFLAGS']
        context.env.Append(CCFLAGS = flags)
        context.env.Append(LINKFLAGS = linkflags)
        result = context.TryCompile("int main() {return 0;}", '.c')
        context.env.Replace(CCFLAGS = oldflags)
        context.env.Replace(LINKFLAGS = oldlinkflags)
        context.Result(result)
        return result
    
    conf = Configure(env, custom_tests = {'CheckCCFLAGS': check_ccflags})

    # If the platform doesn't support C99, use our own header file instead.
    stdbool = conf.CheckCHeader('stdbool.h')
    stdint = conf.CheckCHeader('stdint.h')
    stddef = conf.CheckCHeader('stddef.h')
    string = conf.CheckCHeader('string.h')
    stdlib = conf.CheckCHeader('stdlib.h')
    limits = conf.CheckCHeader('limits.h')
    if not stdbool or not stdint or not stddef or not string or not limits:
        conf.env.Append(CPPDEFINES = {'PB_SYSTEM_HEADER': '\\"pb_syshdr.h\\"'})
        conf.env.Append(CPPPATH = "#../extra")
        conf.env.Append(SYSHDR = '\\"pb_syshdr.h\\"')
        
        if stdbool: conf.env.Append(CPPDEFINES = {'HAVE_STDBOOL_H': 1})
        if stdint: conf.env.Append(CPPDEFINES = {'HAVE_STDINT_H': 1})
        if stddef: conf.env.Append(CPPDEFINES = {'HAVE_STDDEF_H': 1})
        if string: conf.env.Append(CPPDEFINES = {'HAVE_STRING_H': 1})
        if stdlib: conf.env.Append(CPPDEFINES = {'HAVE_STDLIB_H': 1})
        if limits: conf.env.Append(CPPDEFINES = {'HAVE_LIMITS_H': 1})
    
    # Check if we can use pkg-config to find protobuf include path
    status, output = conf.TryAction('pkg-config protobuf --variable=includedir > $TARGET')
    if status:
        conf.env.Append(PROTOCPATH = output.strip())
    else:
        conf.env.Append(PROTOCPATH = '/usr/include')
    
    # Check protoc version
    status, output = conf.TryAction('$PROTOC --version > $TARGET')
    if status:
        conf.env['PROTOC_VERSION'] = output

    # Check if libmudflap is available (only with GCC)
    if 'gcc' in env['CC']:
        if conf.CheckLib('mudflap'):
            conf.env.Append(CCFLAGS = '-fmudflap')
            conf.env.Append(LINKFLAGS = '-fmudflap')
    
    # Check if we can use extra strict warning flags (only with GCC)
    extra = '-Wcast-qual -Wlogical-op -Wconversion'
    extra += ' -fstrict-aliasing -Wstrict-aliasing=1'
    extra += ' -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls'
    extra += ' -Wstack-protector '
    if 'gcc' in env['CC']:
        if conf.CheckCCFLAGS(extra):
            conf.env.Append(CORECFLAGS = extra)
    
    # Check if we can use undefined behaviour sanitizer (only with clang)
    # TODO: Fuzz test triggers the bool sanitizer, figure out whether to
    #       modify the fuzz test or to keep ignoring the check.
    extra = '-fsanitize=undefined,integer -fno-sanitize-recover=undefined,integer '
    if 'clang' in env['CC']:
        if conf.CheckCCFLAGS(extra, linkflags = extra):
            conf.env.Append(CORECFLAGS = extra)
            conf.env.Append(LINKFLAGS = extra)
    
    # End the config stuff
    env = conf.Finish()

# Initialize the CCFLAGS according to the compiler
if 'gcc' in env['CC']:
    # GNU Compiler Collection
    
    # Debug info, warnings as errors
    env.Append(CFLAGS = '-g -Wall -Werror ')
    env.Append(CORECFLAGS = '-Wextra')
    
    # Pedantic ANSI C. On AVR this doesn't work because we use large
    # enums in some of the tests.
    if env.get("EMBEDDED") != "AVR":
        env.Append(CFLAGS = '-ansi -pedantic')
    
    # Profiling and coverage
    if not env.get("EMBEDDED"):
        env.Append(CFLAGS = '-fprofile-arcs -ftest-coverage ')
        env.Append(LINKFLAGS = '-g --coverage')
        
    
    # We currently need uint64_t anyway, even though ANSI C90 otherwise..
    env.Append(CFLAGS = '-Wno-long-long')
elif 'clang' in env['CC']:
    # CLang
    env.Append(CFLAGS = '-ansi -g -Wall -Werror')
    env.Append(CORECFLAGS = ' -Wextra -Wcast-qual -Wconversion')
elif 'cl' in env['CC']:
    # Microsoft Visual C++
    
    # Debug info on, warning level 2 for tests, warnings as errors
    env.Append(CFLAGS = '/Zi /W2 /WX')
    env.Append(LINKFLAGS = '/DEBUG')
    
    # More strict checks on the nanopb core
    env.Append(CORECFLAGS = '/W4')

    # Disable warning about sizeof(union{}) construct that is used in
    # message size macros, in e.g. multiple_files testcase. The C construct
    # itself is valid, but quite rare, which causes Visual C++ to give a warning
    # about it.
    env.Append(CFLAGS = '/wd4116')
elif 'tcc' in env['CC']:
    # Tiny C Compiler
    env.Append(CFLAGS = '-Wall -Werror -g')

env.SetDefault(CORECFLAGS = '')

if 'clang' in env['CXX']:
    env.Append(CXXFLAGS = '-g -Wall -Werror -Wextra -Wno-missing-field-initializers')
elif 'g++' in env['CXX'] or 'gcc' in env['CXX']:
    env.Append(CXXFLAGS = '-g -Wall -Werror -Wextra -Wno-missing-field-initializers')
elif 'cl' in env['CXX']:
    env.Append(CXXFLAGS = '/Zi /W2 /WX /wd4116 /wd4127')

if not env.get("EMBEDDED"):
    valgrind = env.WhereIs('valgrind')
    if valgrind:
        env.SetDefault(VALGRIND = valgrind)

# Now include the SConscript files from all subdirectories
import os.path
env['VARIANT_DIR'] = 'build'
env['BUILD'] = '#' + env['VARIANT_DIR']
env['COMMON'] = '#' + env['VARIANT_DIR'] + '/common'

# Include common/SConscript first to make sure its exports are available
# to other SConscripts.
SConscript("common/SConscript", exports = 'env', variant_dir = env['VARIANT_DIR'] + '/common')

for subdir in Glob('*/SConscript') + Glob('regression/*/SConscript'):
    if str(subdir).startswith("common"): continue
    SConscript(subdir, exports = 'env', variant_dir = env['VARIANT_DIR'] + '/' + os.path.dirname(str(subdir)))

