• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3# Copyright 2020-2022 The Khronos Group Inc.
4#
5# SPDX-License-Identifier: Apache-2.0
6
7# Build a spec with requested extension sets and options.
8#
9# Usage: makeSpec script-options make-options
10# Script options are parsed by this script before invoking 'make':
11#   -genpath path - directory for generated files and outputs
12#   -spec core - make a spec with no extensions (default)
13#   -spec khr - make a spec with all KHR extensions
14#   -spec all - make a spec with all registered extensions
15#   -version {1.0 | 1.1 | 1.2 | 1.3} - make a spec with this core version
16#   -ext name - add specified extension and its dependencies
17#   -clean - clean generated files before building
18#   -registry path - API XML to use instead of default
19#   -apiname name - API name to use instead of default
20#   -v - verbose, print actions before executing  them
21#   -n - dry-run, print actions instead of executing them
22# make-options - all other options are passed to 'make', including
23# requested build targets
24
25import argparse, copy, io, os, re, string, subprocess, sys
26
27def execute(args, results):
28    if results.verbose or results.dryrun:
29        print("'" + "' '".join(args) + "'")
30    if not results.dryrun:
31        subprocess.check_call(args)
32
33if __name__ == '__main__':
34    parser = argparse.ArgumentParser()
35
36    parser.add_argument('-clean', action='store_true',
37                        help='Clean generated files before building')
38    parser.add_argument('-extension', action='append',
39                        default=[],
40                        help='Specify a required extension or extensions to add to targets')
41    parser.add_argument('-genpath', action='store',
42                        default='gen',
43                        help='Path to directory containing generated files')
44    parser.add_argument('-spec', action='store',
45                        choices=[ 'core', 'khr', 'all' ],
46                        default='core',
47                        help='Type of spec to generate')
48    parser.add_argument('-version', action='store',
49                        choices=[ '1.0', '1.1', '1.2', '1.3' ],
50                        default='1.3',
51                        help='Type of spec to generate')
52
53    parser.add_argument('-registry', action='store',
54                        default=None,
55                        help='Path to API XML registry file specifying version and extension dependencies')
56    parser.add_argument('-apiname', action='store',
57                        default=None,
58                        help='API name to generate')
59
60    parser.add_argument('-n', action='store_true', dest='dryrun',
61                        help='Only prints actions, do not execute them')
62    parser.add_argument('-v', action='store_true', dest='verbose',
63                        help='Print actions before executing them')
64
65    (results, options) = parser.parse_known_args()
66
67    # Ensure genpath is an absolute path, not relative
68    if results.genpath[0] != '/':
69        results.genpath = os.getcwd() + '/' + results.genpath
70
71    # Look for scripts/extdependency.py
72    # This requires makeSpec to be invoked from the repository root, but we
73    # could derive that path.
74    sys.path.insert(0, 'scripts')
75    from extdependency import ApiDependencies
76    deps = ApiDependencies(results.registry, results.apiname)
77
78    # List of versions to build with from the requested -version
79    # This should come from the extdependency module as well, eventually
80    versionDict = {
81        '1.0' : [ 'VK_VERSION_1_0' ],
82        '1.1' : [ 'VK_VERSION_1_0', 'VK_VERSION_1_1' ],
83        '1.2' : [ 'VK_VERSION_1_0', 'VK_VERSION_1_1', 'VK_VERSION_1_2' ],
84        '1.3' : [ 'VK_VERSION_1_0', 'VK_VERSION_1_1', 'VK_VERSION_1_2', 'VK_VERSION_1_3' ],
85    }
86    versions = 'VERSIONS={}'.format(' '.join(versionDict[results.version]))
87
88    # List of extensions to build with from the requested -spec
89    # Also construct a spec title
90    # This should respect version dependencies as well
91    if results.spec == 'core':
92        title = ''
93        exts = set()
94    if results.spec == 'khr':
95        title = 'with all KHR extensions'
96        exts = set(deps.khrExtensions())
97    elif results.spec == 'all':
98        title = 'with all registered extensions'
99        exts = set(deps.allExtensions())
100
101    # List of explicitly requested extension and all its dependencies
102    extraexts = set()
103    for name in results.extension:
104        if name in deps.allExtensions():
105            extraexts.add(name)
106            extraexts.update(deps.children(name))
107        else:
108            raise Exception(f'ERROR: unknown extension {name}')
109
110    # See if any explicitly requested extensions are not implicitly requested
111    # Add any such extensions to the spec title
112    extraexts -= exts
113    if len(extraexts) > 0:
114        exts.update(extraexts)
115        if title != '':
116            title += ' and ' + ', '.join(sorted(extraexts))
117        else:
118            title += 'with ' + ', '.join(sorted(extraexts))
119
120    if title != '':
121        title = '(' + title + ')'
122
123    # Finally, actually invoke make as needed for the targets
124    args = [ 'make', 'GENERATED=' + results.genpath ]
125
126    if results.clean:
127        # If OUTDIR is set on the command line, pass it to the 'clean'
128        # target so it is cleaned as well.
129        cleanopts = ['clean']
130        for opt in options:
131            if opt[:7] == 'OUTDIR=':
132                cleanopts.append(opt)
133        try:
134            execute(args + cleanopts, results)
135        except:
136            sys.exit(1)
137
138    args.append(versions)
139
140    # The actual target
141    if len(exts) > 0:
142        args.append(f'EXTENSIONS={" ".join(sorted(exts))}')
143    args.append(f'APITITLE={title}')
144    args += options
145
146    try:
147        execute(args, results)
148    except:
149        sys.exit(1)
150