import os
import platform

#version info of the library, we use 5 chars from the git hash
revision = os.popen('git describe --abbrev=5 --dirty --always').read()[:-1]

version_info =  {
    'version_major':  1 ,
    'version_minor':  0 ,
    'version_patch':  0 ,
    'version_revision': revision,
#version_abi is the abi version of the shared library. Only bump it when
#backwards compatibility breaks. Strive to not break the ABI.
    'version_abi':    '1.0.0'
}
version_info['version_str'] = "%d.%d.%d.%s" % (
    version_info['version_major'],
    version_info['version_minor'],
    version_info['version_patch'],
    version_info['version_revision'])


AddOption('--build_type',
            dest = 'build_type',
            type = 'choice',
            nargs = 1,
            action='store',
            default='debug',
            metavar='TYPE',
            choices = ['debug', 'release'],
            help = 'debug|release - Build a Debug (default) or Release variant'
)
AddOption('--prefix',
            dest='prefix',
            type='string',
            nargs=1,
            action='store',
            metavar='DIR',
            default='/usr',
            help='installation prefix'
)

AddOption('--test_xml',
            dest='test_xml',
            action='store_true',
            help='Create a result.xml when running the testsuite'
)

AddOption('--coverage',
            dest='coverage',
            action='store_true',
            help='Build with coverage (gcov) support'
)

AddOption('--without-assertions',
            dest='assertions',
            action='store_false',
            default=True,
            help='Build without assertions enabled'
)

AddOption('--stack-protection',
            dest = 'stack_protection',
            action='store_true',
            default=False,
            help = 'Build with stack protection support'
)

AddOption('--32',
            dest='force32bit',
            action='store_true',
            default=False,
            help='Force building for 32 bit architecture'
)

build_type = GetOption('build_type')
assertions = GetOption('assertions')
stack_protection = GetOption('stack_protection')
test_xml = GetOption('test_xml')
prefix = GetOption('prefix')
lib_suffix = ''
if not (build_type in ['debug', 'release']):
    print("Error: expected 'debug' or 'release', found: " + build_type)
    Exit(1)

def InstallPerm(env, dest, files, perm):
    obj = env.Install(dest, files)
    for i in obj:
        env.AddPostAction(i, Chmod(str(i), perm))
    return obj


env = Environment(tools = ['default', 'textfile', 'packaging'])

#allow shell environment to override compiler
if os.environ.get('CC'):
    env['CC'] = os.environ['CC']

env.AddMethod(InstallPerm)

env.Append(CFLAGS = ['-std=gnu99','-Wall', '-Wextra', '-Wundef', '-Wcast-qual','-Wshadow' ,'-Wcast-align','-pipe', '-ggdb', '-pthread'])
env.Append(CFLAGS = ['-Wno-unused-parameter', '-Werror=implicit-function-declaration', '-Winit-self'])
env.Append(LINKFLAGS = ['-O2', '-pthread'])
env.Append(CPPDEFINES = ['_FILE_OFFSET_BITS=64'])
env.Append(CPPPATH = ['#include'])
env.Append(SHLIBVERSION = version_info['version_abi'])

if GetOption('force32bit'):
    env.Append(CFLAGS = ['-m32'])
    env.Append(LINKFLAGS = ['-m32'])

if build_type == 'release':
    env.Append(CFLAGS = ['-O2'])
elif build_type == 'debug':
    lib_suffix = 'D'
    env.Append(CPPDEFINES = ['DEBUG'])

if stack_protection:
    env.Append(CFLAGS = ['-fstack-protector', '--param=ssp-buffer-size=4'])
    env.Append(CPPDEFINES = ['_FORTIFY_SOURCE=2'])
if not assertions:
    #this will turn off assert()
    env.Append(CPPDEFINES = ['NDEBUG'])

if GetOption('coverage'):
    env.Append(CFLAGS = ['--coverage'])
    env.Append(LINKFLAGS = ['--coverage'])

# Generate substitute dictionary
subst_info = dict(('@' + key + '@', version_info[key]) for key in version_info)
subst_info['@prefix@'] = prefix
subst_info['@build_type@'] = build_type

if assertions:
    subst_info['@build_type@'] += '_A'
if stack_protection:
    subst_info['@build_type@'] += '_SP'

subst_info['@build_host@'] = platform.node()

Export('env', 'build_type', 'prefix', 'lib_suffix', 'version_info', 'test_xml', 'subst_info')

#put all .sconsign files in one place
env.SConsignFile()

subdirs = [
'src',
'include',
'test',
]

for subdir in subdirs:
    env.SConscript(subdir + '/SConscript', variant_dir='#build/' + subdir, src_dir='#'+subdir, duplicate=0)

env.Package(target = 'libucore-' + version_info['version_str'] + '.tar.gz',
            source         = env.FindInstalledFiles(),
            NAME           = 'libucore',
            VERSION        = version_info['version_str'],
            PACKAGEVERSION = 0,
            PACKAGETYPE    = 'targz',
            LICENSE        = 'BSD',
            SUMMARY        = 'libucore is a C library of misc useful stuff including an eventloop, timer support and various data-structures.',
            DESCRIPTION    = 'libucore is a C library of misc useful stuff including an eventloop, timer support and various data-structures.',
            X_RPM_GROUP    = 'Development/Libraries'
)

env.Default('src')
