#!/usr/bin/python

lib_srcs = [
        'cdb.c', 'parse_inquiry.c', 'ata.c', 'parse_sense.c', 'parse_read_cap.c', 'str_map.c', 'ata_smart.c',
        'smartdb/smartdb.c', 'smartdb/smartdb_gen.c',
]

test_srcs = {
        'ata_check_power_mode': [],
        'ata_smart_read_data': [],
        'ata_smart_return_status': [],
        'scsi_inquiry': [],
        'scsi_log_sense': [],
        'scsi_read_capacity_10': [],
        #'ata_identify': ['ata_identify_dump.c'],
}

cflags = ['-Iinclude', '-g', '-O0', '-Wall', '-Werror', '-Wextra', '-Wshadow',
          '-Wmissing-prototypes', '-Winit-self', '-pipe', '-D_GNU_SOURCE',
          '-D_FORTIFY_SOURCE=2']
ldflags = []

import os, os.path
import glob
import ninja_syntax
import sys

is_lib_only = '--lib-only' in sys.argv
lib_prefix = ''
if is_lib_only:
    lib_prefix = 'libscsicmd/'
    lib_srcs = map(lambda x: lib_prefix + x, lib_srcs)

# Top level ninja
n = ninja_syntax.Writer(open('build.ninja', 'w'))
n.comment('Auto generated by ./configure, edit the configure script instead')
n.newline()

env_keys = set(['CC', 'AR', 'CFLAGS', 'LDFLAGS'])
configure_env = dict((k, os.environ[k]) for k in os.environ if k in env_keys)
if configure_env:
    config_str = ' '.join([k+'='+configure_env[k] for k in configure_env])
    n.variable('configure_env', config_str+'$ ')
n.newline()

CC = configure_env.get('CC', 'gcc')
n.variable('cc', CC)
AR = configure_env.get('AR', 'ar')
n.variable('ar', AR)
n.newline()

def shell_escape(str):
        """Escape str such that it's interpreted as a single argument by
           the shell."""

        # This isn't complete, but it's just enough to make NINJA_PYTHON work.
        if '"' in str:
                return "'%s'" % str.replace("'", "\\'")
        return str

if 'CFLAGS' in configure_env:
    cflags.append(configure_env['CFLAGS'])
n.variable('cflags', ' '.join(shell_escape(flag) for flag in cflags))

if 'LDFLAGS' in configure_env:
    ldflags.append(configure_env['LDFLAGS'])
n.variable('ldflags', ' '.join(shell_escape(flag) for flag in ldflags))

n.newline()

n.rule('c',
        command='$cc -MMD -MT $out -MF $out.d $cflags $extracflags -c $in -o $out',
        depfile='$out.d',
        deps='gcc',
        description='CC $out'
)
n.newline()

n.rule('ar',
        command='rm -f $out && $ar crs $out $in',
        description='AR $out',
)
n.newline()

n.rule('link',
        command='$cc -o $out $in $libs $ldflags',
        description='LINK $out'
)
n.newline()

def with_prefix(filename):
        return os.path.join('$libscsicmd_prefix', filename)

def src(filename):
        return os.path.join('$libscsicmd_prefix', 'src', filename)
def btest(filename):
        return os.path.join('$libscsicmd_prefix', 'test', filename)
def built(filename):
        return os.path.join('built', '$libscsicmd', filename)
def cc(filename, **kwargs):
        return n.build(built(filename)[:-2] + '.o', 'c', src(filename), **kwargs)

def script(filename, srcfile, scriptfile):
    filename = with_prefix(filename)
    srcfile = with_prefix(srcfile)
    scriptfile = with_prefix(scriptfile)
    return n.build(filename, 'script', srcfile, implicit=scriptfile, variables=[('script', scriptfile)])

n.rule('configure',
        command='${configure_env} ./configure',
        description='CONFIGURE build.ninja',
        generator=True
        )
n.newline()

n.rule('tags',
        command='ctags $in',
        description='CTAGS $out'
        )
n.newline()

n.variable('libscsicmd_prefix', '.')

n.subninja('lib.ninja')
n.subninja('tests.ninja')

n.build('all', 'phony', ['configure', 'tags', 'lib', 'tests'])
n.default('all')

# Library ninja
n = ninja_syntax.Writer(open('lib.ninja', 'w'))
n.comment('Auto generated by ./configure, edit the configure script instead')
n.newline()

n.rule('script',
        command='$script $in > $out',
        description='SCRIPT $script $in'
)
n.newline()

smartdb_gen_c = script('src/smartdb/smartdb_gen.c', 'src/smartdb/smartdb.xml', 'src/smartdb/smartdb_gen_c.py')
ata_parse_h = script('include/ata_parse.h', 'structs/ata_identify.yaml', 'structs/ata_struct_2_h.py')

lib_objs = []
for source in lib_srcs:
        lib_objs += cc(source)
lib = n.build('libscsicmd.a', 'ar', lib_objs, implicit=ata_parse_h)
n.build('lib', 'phony', lib)
n.newline()

# Tests/tools ninja
def src(filename):
        return os.path.join('$libscsicmd_prefix', 'test', filename)

n = ninja_syntax.Writer(open('tests.ninja', 'w'))
n.comment('Auto generated by ./configure, edit the configure script instead')
n.newline()

ata_identify_dump_h = script('test/ata_identify_dump.h', 'structs/ata_identify.yaml', 'structs/ata_struct_2_h_dump.py')

test_targets = []
test_exec = []
test_objs = {}
for test in test_srcs.keys():
        objs = []
        test_src = test_srcs[test] + ['main.c', 'sense_dump.c', test + '.c']
        for source in test_src:
                if source in test_objs.keys():
                        objs += test_objs[source]
                else:
                        obj = cc(source, implicit=ata_parse_h+ata_identify_dump_h)
                        test_objs[source] = obj
                        objs += obj
        test_exec += n.build(test, 'link', objs, implicit=lib, variables=[('libs', lib)])
        test_targets += test_exec
n.newline()

n.build('tests', 'phony', test_targets)

print('Configure done')
