blob: fade64a902269cfaf32d8a55d4fb005f4099ae63 [file] [log] [blame]
Gurchetan Singhcb8d37c2023-11-06 10:19:32 -08001#!/usr/bin/env python3
2#
3# Copyright 2020-2023 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 ratified - make a spec with all ratified (KHR + some EXT) extensions
15# -spec all - make a spec with all registered extensions
16# -version {1.0 | 1.1 | 1.2 | 1.3 | sc1.0} - make a spec with this core version
17# -ext name - add specified extension and its dependencies
18# -clean - clean generated files before building
19# -registry path - API XML to use instead of default
20# -apiname name - API name to use instead of default
21# -test - Build the test spec instead
22# -v - verbose, print actions before executing them
23# -n - dry-run, print actions instead of executing them
24# make-options - all other options are passed to 'make', including
25# requested build targets
26
27import argparse, copy, io, os, re, string, subprocess, sys
28
29def execute(args, results):
30 if results.verbose or results.dryrun:
31 print("'" + "' '".join(args) + "'")
32 if not results.dryrun:
33 subprocess.check_call(args)
34
35if __name__ == '__main__':
36 parser = argparse.ArgumentParser()
37
38 parser.add_argument('-clean', action='store_true',
39 help='Clean generated files before building')
40 parser.add_argument('-extension', action='append',
41 default=[],
42 help='Specify a required extension or extensions to add to targets')
43 parser.add_argument('-genpath', action='store',
44 default='gen',
45 help='Path to directory containing generated files')
46 parser.add_argument('-spec', action='store',
47 choices=[ 'core', 'khr', 'ratified', 'all' ],
48 default='core',
49 help='Type of spec to generate')
50 parser.add_argument('-version', action='store',
51 choices=[ '1.0', '1.1', '1.2', '1.3', 'sc1.0' ],
52 default='1.3',
53 help='Type of spec to generate')
54 parser.add_argument('-registry', action='store',
55 default=None,
56 help='Path to API XML registry file specifying version and extension dependencies')
57 parser.add_argument('-apiname', action='store',
58 default=None,
59 help='API name to generate')
60 parser.add_argument('-test', action='store_true',
61 help='Build the test spec instead of the Vulkan spec')
62 parser.add_argument('-n', action='store_true', dest='dryrun',
63 help='Only prints actions, do not execute them')
64 parser.add_argument('-v', action='store_true', dest='verbose',
65 help='Print actions before executing them')
66
67 (results, options) = parser.parse_known_args()
68
69 # Ensure genpath is an absolute path, not relative
70 if results.genpath[0] != '/':
71 results.genpath = os.getcwd() + '/' + results.genpath
72
73 # Look for scripts/extdependency.py
74 # This requires makeSpec to be invoked from the repository root, but we
75 # could derive that path.
76 sys.path.insert(0, 'scripts')
77 from extdependency import ApiDependencies
78 deps = ApiDependencies(results.registry, results.apiname)
79
80 # List of versions to build with from the requested -version
81 # This should come from the extdependency module as well, eventually
82 #@ Note that at present, building sc1.0 does *not* include Vulkan 1.3 automatically.
83 versionDict = {
84 '1.0' : [ 'VK_VERSION_1_0' ],
85 '1.1' : [ 'VK_VERSION_1_0', 'VK_VERSION_1_1' ],
86 '1.2' : [ 'VK_VERSION_1_0', 'VK_VERSION_1_1', 'VK_VERSION_1_2' ],
87 '1.3' : [ 'VK_VERSION_1_0', 'VK_VERSION_1_1', 'VK_VERSION_1_2', 'VK_VERSION_1_3' ],
88 'sc1.0' : [ 'VK_VERSION_1_0', 'VK_VERSION_1_1', 'VK_VERSION_1_2', 'VKSC_VERSION_1_0' ],
89 }
90 versions = 'VERSIONS={}'.format(' '.join(versionDict[results.version]))
91
92 # List of extensions to build with from the requested -spec
93 # Also construct a spec title
94 # This should respect version dependencies as well
95 if results.spec == 'core':
96 title = ''
97 exts = set()
98 elif results.spec == 'khr':
99 title = 'with all KHR extensions'
100 exts = set(deps.khrExtensions())
101 elif results.spec == 'ratified':
102 title = 'with all ratified extensions'
103 exts = set(deps.ratifiedExtensions())
104 elif results.spec == 'all':
105 title = 'with all registered extensions'
106 exts = set(deps.allExtensions())
107
108 # List of explicitly requested extension and all its supported dependencies
109 extraexts = set()
110 for name in results.extension:
111 if name in deps.allExtensions():
112 extraexts.add(name)
113 for dep in deps.children(name):
114 if dep in deps.allExtensions():
115 extraexts.update({dep})
116 else:
117 raise Exception(f'ERROR: unknown extension {name}')
118
119 # See if any explicitly requested extensions are not implicitly requested
120 # Add any such extensions to the spec title
121 extraexts -= exts
122 if len(extraexts) > 0:
123 exts.update(extraexts)
124 if title != '':
125 title += ' and ' + ', '.join(sorted(extraexts))
126 else:
127 title += 'with ' + ', '.join(sorted(extraexts))
128
129 if title != '':
130 title = '(' + title + ')'
131
132 # Finally, actually invoke make as needed for the targets
133 args = [ 'make', 'GENERATED=' + results.genpath ]
134
135 if results.clean:
136 # If OUTDIR is set on the command line, pass it to the 'clean'
137 # target so it is cleaned as well.
138 cleanopts = ['clean']
139 for opt in options:
140 if opt[:7] == 'OUTDIR=':
141 cleanopts.append(opt)
142 try:
143 execute(args + cleanopts, results)
144 except:
145 sys.exit(1)
146
147 # Use the test spec if specified. This is used solely by self tests.
148 rootdir = os.path.dirname(os.path.abspath(__file__))
149 if results.test:
150 # Set the spec source to the test spec
151 args.append(f'SPECSRC={rootdir}/build_tests/testspec.adoc')
152 args.append(f'SPECDIR={rootdir}/build_tests/')
153 # Make sure the build is invariant
154 args.append('SPECREVISION=1.2.3')
155 args.append('SPECDATE=\\"2100-11-22 00:33:44Z\\"')
156 args.append('SPECREMARK=\\"test build\\"')
157
158 args.append(versions)
159
160 # The actual target
161 if len(exts) > 0:
162 args.append(f'EXTENSIONS={" ".join(sorted(exts))}')
163 args.append(f'APITITLE={title}')
164 args += options
165
166 try:
167 execute(args, results)
168 except:
169 sys.exit(1)