#!/usr/bin/env python3
#
# Copyright 2020-2023 The Khronos Group Inc.
#
# SPDX-License-Identifier: Apache-2.0

# Build a spec with requested extension sets and options.
#
# Usage: makeSpec script-options make-options
# Script options are parsed by this script before invoking 'make':
#   -genpath path - directory for generated files and outputs
#   -spec core - make a spec with no extensions (default)
#   -spec khr - make a spec with all KHR extensions
#   -spec ratified - make a spec with all ratified (KHR + some EXT) extensions
#   -spec all - make a spec with all registered extensions
#   -version {1.0 | 1.1 | 1.2 | 1.3 | sc1.0} - make a spec with this core version
#   -ext name - add specified extension and its dependencies
#   -clean - clean generated files before building
#   -registry path - API XML to use instead of default
#   -apiname name - API name to use instead of default
#   -test - Build the test spec instead
#   -v - verbose, print actions before executing  them
#   -n - dry-run, print actions instead of executing them
# make-options - all other options are passed to 'make', including
# requested build targets

import argparse, copy, io, os, re, string, subprocess, sys

def execute(args, results):
    if results.verbose or results.dryrun:
        print("'" + "' '".join(args) + "'")
    if not results.dryrun:
        subprocess.check_call(args)

if __name__ == '__main__':
    parser = argparse.ArgumentParser()

    parser.add_argument('-clean', action='store_true',
                        help='Clean generated files before building')
    parser.add_argument('-extension', action='append',
                        default=[],
                        help='Specify a required extension or extensions to add to targets')
    parser.add_argument('-genpath', action='store',
                        default='gen',
                        help='Path to directory containing generated files')
    parser.add_argument('-spec', action='store',
                        choices=[ 'core', 'khr', 'ratified', 'all' ],
                        default='core',
                        help='Type of spec to generate')
    parser.add_argument('-version', action='store',
                        choices=[ '1.0', '1.1', '1.2', '1.3', 'sc1.0' ],
                        default='1.3',
                        help='Type of spec to generate')
    parser.add_argument('-registry', action='store',
                        default=None,
                        help='Path to API XML registry file specifying version and extension dependencies')
    parser.add_argument('-apiname', action='store',
                        default=None,
                        help='API name to generate')
    parser.add_argument('-test', action='store_true',
                        help='Build the test spec instead of the Vulkan spec')
    parser.add_argument('-n', action='store_true', dest='dryrun',
                        help='Only prints actions, do not execute them')
    parser.add_argument('-v', action='store_true', dest='verbose',
                        help='Print actions before executing them')

    (results, options) = parser.parse_known_args()

    # Ensure genpath is an absolute path, not relative
    if results.genpath[0] != '/':
        results.genpath = os.getcwd() + '/' + results.genpath

    # Look for scripts/extdependency.py
    # This requires makeSpec to be invoked from the repository root, but we
    # could derive that path.
    sys.path.insert(0, 'scripts')
    from extdependency import ApiDependencies
    deps = ApiDependencies(results.registry, results.apiname)

    # List of versions to build with from the requested -version
    # This should come from the extdependency module as well, eventually
    #@ Note that at present, building sc1.0 does *not* include Vulkan 1.3 automatically.
    versionDict = {
        '1.0' : [ 'VK_VERSION_1_0' ],
        '1.1' : [ 'VK_VERSION_1_0', 'VK_VERSION_1_1' ],
        '1.2' : [ 'VK_VERSION_1_0', 'VK_VERSION_1_1', 'VK_VERSION_1_2' ],
        '1.3' : [ 'VK_VERSION_1_0', 'VK_VERSION_1_1', 'VK_VERSION_1_2', 'VK_VERSION_1_3' ],
        'sc1.0' : [ 'VK_VERSION_1_0', 'VK_VERSION_1_1', 'VK_VERSION_1_2', 'VKSC_VERSION_1_0' ],
    }
    versions = 'VERSIONS={}'.format(' '.join(versionDict[results.version]))

    # List of extensions to build with from the requested -spec
    # Also construct a spec title
    # This should respect version dependencies as well
    if results.spec == 'core':
        title = ''
        exts = set()
    elif results.spec == 'khr':
        title = 'with all KHR extensions'
        exts = set(deps.khrExtensions())
    elif results.spec == 'ratified':
        title = 'with all ratified extensions'
        exts = set(deps.ratifiedExtensions())
    elif results.spec == 'all':
        title = 'with all registered extensions'
        exts = set(deps.allExtensions())

    # List of explicitly requested extension and all its supported dependencies
    extraexts = set()
    for name in results.extension:
        if name in deps.allExtensions():
            extraexts.add(name)
            for dep in deps.children(name):
                if dep in deps.allExtensions():
                    extraexts.update({dep})
        else:
            raise Exception(f'ERROR: unknown extension {name}')

    # See if any explicitly requested extensions are not implicitly requested
    # Add any such extensions to the spec title
    extraexts -= exts
    if len(extraexts) > 0:
        exts.update(extraexts)
        if title != '':
            title += ' and ' + ', '.join(sorted(extraexts))
        else:
            title += 'with ' + ', '.join(sorted(extraexts))

    if title != '':
        title = '(' + title + ')'

    # Finally, actually invoke make as needed for the targets
    args = [ 'make', 'GENERATED=' + results.genpath ]

    if results.clean:
        # If OUTDIR is set on the command line, pass it to the 'clean'
        # target so it is cleaned as well.
        cleanopts = ['clean']
        for opt in options:
            if opt[:7] == 'OUTDIR=':
                cleanopts.append(opt)
        try:
            execute(args + cleanopts, results)
        except:
            sys.exit(1)

    # Use the test spec if specified.  This is used solely by self tests.
    rootdir = os.path.dirname(os.path.abspath(__file__))
    if results.test:
        # Set the spec source to the test spec
        args.append(f'SPECSRC={rootdir}/build_tests/testspec.adoc')
        args.append(f'SPECDIR={rootdir}/build_tests/')
        # Make sure the build is invariant
        args.append('SPECREVISION=1.2.3')
        args.append('SPECDATE=\\"2100-11-22 00:33:44Z\\"')
        args.append('SPECREMARK=\\"test build\\"')

    args.append(versions)

    # The actual target
    if len(exts) > 0:
        args.append(f'EXTENSIONS={" ".join(sorted(exts))}')
    args.append(f'APITITLE={title}')
    args += options

    try:
        execute(args, results)
    except:
        sys.exit(1)
