3 # Copyright (c) 2013-2024 The Khronos Group Inc.
4 # Copyright (c) 2023-2024 RasterGrid Kft.
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
10 # http://www.apache.org/licenses/LICENSE-2.0
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
26 # Simple timer functions
30 def startTimer(timeit
):
33 startTime
= time
.process_time()
36 def endTimer(timeit
, msg
):
39 endTime
= time
.process_time()
40 write(msg
, endTime
- startTime
, file=sys
.stderr
)
43 # Turn a list of strings into a regexp string matching exactly those strings
46 def makeREstring(list, default
=None):
47 if len(list) > 0 or default
is None:
48 return '^(' + '|'.join(list) + ')$'
52 # Returns a directory of [ generator function, generator options ] indexed
53 # by specified short names. The generator options incorporate the following
56 # args is an parsed argument object; see below for the fields that are used.
59 def makeGenOpts(args
):
63 # API to generate sources for
66 # Default class of extensions to include, or None
67 if args
.defaultExtensions
is not None:
68 defaultExtensions
= args
.defaultExtensions
70 defaultExtensions
= apiname
72 # Additional extensions to include (list of extensions)
73 extensions
= args
.extension
75 # Extensions to remove (list of extensions)
76 removeExtensions
= args
.removeExtensions
78 # Extensions to emit (list of extensions)
79 emitExtensions
= args
.emitExtensions
81 # Features to include (list of features)
82 features
= args
.feature
84 # Whether to disable inclusion protect in headers
85 protect
= args
.protect
87 # Output target directory
88 directory
= args
.directory
90 # Path to generated files, particularly api.py
91 genpath
= args
.genpath
93 # Descriptive names for various regexp patterns used to select
94 # versions and extensions
95 allFeatures
= allExtensions
= '.*'
96 noFeatures
= noExtensions
= None
98 # Turn lists of names/patterns into matching regular expressions
99 addExtensionsPat
= makeREstring(extensions
, None)
100 removeExtensionsPat
= makeREstring(removeExtensions
, None)
101 emitExtensionsPat
= makeREstring(emitExtensions
, allExtensions
)
102 featuresPat
= makeREstring(features
, allFeatures
)
104 # Copyright text prefixing all headers (list of strings).
107 '** Copyright (c) 2015-2024 The Khronos Group Inc.',
109 '** Licensed under the Apache License, Version 2.0 (the "License");',
110 '** you may not use this file except in compliance with the License.',
111 '** You may obtain a copy of the License at',
113 '** http://www.apache.org/licenses/LICENSE-2.0',
115 '** Unless required by applicable law or agreed to in writing, software',
116 '** distributed under the License is distributed on an "AS IS" BASIS,',
117 '** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.',
118 '** See the License for the specific language governing permissions and',
119 '** limitations under the License.',
124 # Text specific to Vulkan headers
127 '** This header is generated from the Khronos Vulkan XML API Registry.',
133 # Defaults for generating re-inclusion protection wrappers (or not)
134 protectFeature
= protect
136 # An API style conventions object
137 conventions
= VulkanConventions()
139 # Helper file generator options for typemap_helper.h
140 genOpts
['vk_typemap_helper.h'] = [
141 HelperFileOutputGenerator
,
142 HelperFileOutputGeneratorOptions(
143 conventions
=conventions
,
144 filename
='vk_typemap_helper.h',
149 versions
=featuresPat
,
150 emitversions
=featuresPat
,
151 defaultExtensions
=defaultExtensions
,
152 addExtensions
=addExtensionsPat
,
153 removeExtensions
=removeExtensionsPat
,
154 emitExtensions
=emitExtensionsPat
,
155 prefixText
=prefixStrings
+ vkPrefixStrings
,
156 protectFeature
=False,
157 apicall
='VKAPI_ATTR ',
158 apientry
='VKAPI_CALL ',
159 apientryp
='VKAPI_PTR *',
161 expandEnumerants
=False,
162 helper_file_type
='typemap_helper_header')
165 # Options for mock ICD header
166 genOpts
['function_declarations.h'] = [
167 MockICDOutputGenerator
,
168 MockICDGeneratorOptions(
169 conventions
=conventions
,
170 filename
='function_declarations.h',
175 versions
=featuresPat
,
176 emitversions
=featuresPat
,
177 defaultExtensions
=defaultExtensions
,
178 addExtensions
=addExtensionsPat
,
179 removeExtensions
=removeExtensionsPat
,
180 emitExtensions
=emitExtensionsPat
,
181 prefixText
=prefixStrings
+ vkPrefixStrings
,
182 protectFeature
=False,
183 apicall
='VKAPI_ATTR ',
184 apientry
='VKAPI_CALL ',
185 apientryp
='VKAPI_PTR *',
187 expandEnumerants
=False,
188 helper_file_type
='mock_icd_function_declaration_implementation')
191 # Options for mock ICD cpp
192 genOpts
['function_definitions.h'] = [
193 MockICDOutputGenerator
,
194 MockICDGeneratorOptions(
195 conventions
=conventions
,
196 filename
='function_definitions.h',
201 versions
=featuresPat
,
202 emitversions
=featuresPat
,
203 defaultExtensions
=defaultExtensions
,
204 addExtensions
=addExtensionsPat
,
205 removeExtensions
=removeExtensionsPat
,
206 emitExtensions
=emitExtensionsPat
,
207 prefixText
=prefixStrings
+ vkPrefixStrings
,
208 protectFeature
=False,
209 apicall
='VKAPI_ATTR ',
210 apientry
='VKAPI_CALL ',
211 apientryp
='VKAPI_PTR *',
213 expandEnumerants
=False,
214 helper_file_type
='mock_icd_function_definition_implementation')
217 # Options for vulkaninfo.hpp
218 genOpts
['vulkaninfo.hpp'] = [
220 VulkanInfoGeneratorOptions(
221 conventions
=conventions
,
222 filename
='vulkaninfo.hpp',
227 versions
=featuresPat
,
228 emitversions
=featuresPat
,
229 defaultExtensions
=defaultExtensions
,
230 addExtensions
=addExtensionsPat
,
231 removeExtensions
=removeExtensionsPat
,
232 emitExtensions
=emitExtensionsPat
,
233 prefixText
=prefixStrings
+ vkPrefixStrings
,
234 protectFeature
=False,
235 apicall
='VKAPI_ATTR ',
236 apientry
='VKAPI_CALL ',
237 apientryp
='VKAPI_PTR *',
239 expandEnumerants
=False,
240 registryFile
=args
.registry
)
244 # Generate a target based on the options in the matching genOpts{} object.
245 # This is encapsulated in a function so it can be profiled and/or timed.
246 # The args parameter is an parsed argument object containing the following
247 # fields that are used:
248 # target - target to generate
249 # directory - directory to generate it in
250 # protect - True if re-inclusion wrappers should be created
251 # extensions - list of additional extensions to include in generated
256 # Create generator options with specified parameters
259 if (args
.target
in genOpts
.keys()):
260 createGenerator
= genOpts
[args
.target
][0]
261 options
= genOpts
[args
.target
][1]
264 write('* Building', options
.filename
, file=sys
.stderr
)
265 write('* options.apiname =', options
.apiname
, file=sys
.stderr
)
266 write('* options.versions =', options
.versions
, file=sys
.stderr
)
267 write('* options.emitversions =', options
.emitversions
, file=sys
.stderr
)
268 write('* options.defaultExtensions =', options
.defaultExtensions
, file=sys
.stderr
)
269 write('* options.addExtensions =', options
.addExtensions
, file=sys
.stderr
)
270 write('* options.removeExtensions =', options
.removeExtensions
, file=sys
.stderr
)
271 write('* options.emitExtensions =', options
.emitExtensions
, file=sys
.stderr
)
273 gen
= createGenerator(errFile
=errWarn
,
277 write('* Generated', options
.filename
, file=sys
.stderr
)
278 return (gen
, options
)
280 write('No generator options for unknown target:',
281 args
.target
, file=sys
.stderr
)
286 # For both, "name" may be a single name, or a space-separated list
287 # of names, or a regular expression.
288 if __name__
== '__main__':
289 parser
= argparse
.ArgumentParser()
291 parser
.add_argument('-api', action
='store',
293 choices
=['vulkan', 'vulkansc'],
294 help='Specify API name to generate')
295 parser
.add_argument('-defaultExtensions', action
='store',
297 help='Specify a single class of extensions to add to targets')
298 parser
.add_argument('-directory', action
='store', default
='.',
299 help='Specify where the built file is place')
300 parser
.add_argument('-extension', action
='append',
302 help='Specify an extension or extensions to add to targets')
303 parser
.add_argument('-removeExtensions', action
='append',
305 help='Specify an extension or extensions to remove from targets')
306 parser
.add_argument('-emitExtensions', action
='append',
308 help='Specify an extension or extensions to emit in targets')
309 parser
.add_argument('-feature', action
='append',
311 help='Specify a core API feature name or names to add to targets')
312 parser
.add_argument('-debug', action
='store_true',
313 help='Enable debugging')
314 parser
.add_argument('-dump', action
='store_true',
315 help='Enable dump to stderr')
316 parser
.add_argument('-diagfile', action
='store',
318 help='Write diagnostics to specified file')
319 parser
.add_argument('-errfile', action
='store',
321 help='Write errors and warnings to specified file instead of stderr')
322 parser
.add_argument('-noprotect', dest
='protect', action
='store_false',
323 help='Disable inclusion protection in output headers')
324 parser
.add_argument('-profile', action
='store_true',
325 help='Enable profiling')
326 parser
.add_argument('-registry', action
='store',
328 help='Use specified registry file instead of vk.xml')
329 parser
.add_argument('-time', action
='store_true',
330 help='Enable timing')
331 parser
.add_argument('-validate', action
='store_true',
332 help='Enable XML group validation')
333 parser
.add_argument('-genpath', action
='store', default
='gen',
334 help='Path to generated files')
335 parser
.add_argument('-o', action
='store', dest
='directory',
337 help='Create target and related files in specified directory')
338 parser
.add_argument('target', metavar
='target', nargs
='?',
339 help='Specify target')
340 parser
.add_argument('-quiet', action
='store_true', default
=True,
341 help='Suppress script output during normal execution.')
342 parser
.add_argument('-verbose', action
='store_false', dest
='quiet', default
=True,
343 help='Enable script output during normal execution.')
345 # This argument tells us where to load the script from the Vulkan-Headers registry
346 parser
.add_argument('-scripts', action
='store',
347 help='Find additional scripts in this directory')
349 args
= parser
.parse_args()
351 # default scripts path to be same as registry
353 args
.scripts
= os
.path
.dirname(args
.registry
)
355 scripts_directory_path
= os
.path
.dirname(os
.path
.abspath(__file__
))
356 registry_headers_path
= os
.path
.join(scripts_directory_path
, args
.scripts
)
357 sys
.path
.insert(0, registry_headers_path
)
360 from generator
import write
361 from cgenerator
import CGeneratorOptions
, COutputGenerator
363 # Generator Modifications
364 from mock_icd_generator
import MockICDGeneratorOptions
, MockICDOutputGenerator
365 from vulkan_tools_helper_file_generator
import HelperFileOutputGenerator
, HelperFileOutputGeneratorOptions
366 from vulkaninfo_generator
import VulkanInfoGenerator
, VulkanInfoGeneratorOptions
367 # Temporary workaround for vkconventions python2 compatibility
369 abc
.ABC
= abc
.ABCMeta('ABC', (object,), {})
370 from vkconventions
import VulkanConventions
372 # This splits arguments which are space-separated lists
373 args
.feature
= [name
for arg
in args
.feature
for name
in arg
.split()]
374 args
.extension
= [name
for arg
in args
.extension
for name
in arg
.split()]
376 # create error/warning & diagnostic files
378 errWarn
= open(args
.errfile
, 'w', encoding
='utf-8')
383 diag
= open(args
.diagfile
, 'w', encoding
='utf-8')
387 # Create the API generator & generator options
388 (gen
, options
) = genTarget(args
)
390 # Create the registry object with the specified generator and generator
391 # options. The options are set before XML loading as they may affect it.
392 reg
= Registry(gen
, options
)
394 # Parse the specified registry XML into an ElementTree object
395 startTimer(args
.time
)
396 tree
= etree
.parse(args
.registry
)
397 endTimer(args
.time
, '* Time to make ElementTree =')
399 # Load the XML tree into the registry object
400 startTimer(args
.time
)
401 reg
.loadElementTree(tree
)
402 endTimer(args
.time
, '* Time to parse ElementTree =')
408 write('* Dumping registry to regdump.txt', file=sys
.stderr
)
409 reg
.dumpReg(filehandle
= open('regdump.txt', 'w', encoding
='utf-8'))
411 # Finally, use the output generator to create the requested target
413 pdb
.run('reg.apiGen()')
415 startTimer(args
.time
)
417 endTimer(args
.time
, '* Time to generate ' + options
.filename
+ ' =')