# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
top = '..'

from waflib import Options

def options(opt):
    for subdir in opt.path.ant_glob('*', dir=True, src=False):
        tool = subdir.path_from(opt.path)
        opt.add_option('--enable-%s' % tool,
                       help='Build tool %s, enabled by default' % tool,
                       action='store_true', dest='enable_%s' % tool)
        opt.add_option('--disable-%s' % tool,
                       help='Do not build tool %s' % tool,
                       action='store_true', dest='disable_%s' % tool)
        opt.recurse(str(tool), mandatory=False)

def configure(conf):
    all_tools = set() # all available tools
    enabled_tools = set() # --enable-X
    disabled_tools = set() # --disable-X

    Options.options.disable_pib = True

    for subdir in conf.path.ant_glob('*', dir=True, src=False):
        tool = subdir.path_from(conf.path)
        all_tools.add(tool)

        is_enabled = getattr(Options.options, 'enable_%s' % tool)
        is_disabled = getattr(Options.options, 'disable_%s' % tool)

        if is_enabled and is_disabled:
            conf.fatal('--enable-%s and --disable-%s cannot be both specified' % (tool, tool))

        if is_enabled:
            enabled_tools.add(tool)

        if is_disabled:
            disabled_tools.add(tool)

    if len(enabled_tools) == 0:
        conf.env['BUILD_TOOLS'] = list(all_tools - disabled_tools)
    else:
        conf.env['BUILD_TOOLS'] = list(enabled_tools)

    for tool in conf.env['BUILD_TOOLS']:
        conf.recurse(tool, mandatory=False)

def build(bld):
    for tool in bld.env['BUILD_TOOLS']:
        bld.recurse(tool)
