• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/python3
2#
3# Copyright 2013-2022 The Khronos Group Inc.
4#
5# SPDX-License-Identifier: Apache-2.0
6
7import argparse
8import os
9import pdb
10import re
11import sys
12import time
13import xml.etree.ElementTree as etree
14
15sys.path.append(os.path.abspath(os.path.dirname(__file__)))
16
17from cgenerator import CGeneratorOptions, COutputGenerator
18
19from docgenerator import DocGeneratorOptions, DocOutputGenerator
20from extensionmetadocgenerator import (ExtensionMetaDocGeneratorOptions,
21                                       ExtensionMetaDocOutputGenerator)
22from interfacedocgenerator import InterfaceDocGenerator
23from generator import write
24from spirvcapgenerator import SpirvCapabilityOutputGenerator
25from hostsyncgenerator import HostSynchronizationOutputGenerator
26from formatsgenerator import FormatsOutputGenerator
27from pygenerator import PyOutputGenerator
28from rubygenerator import RubyOutputGenerator
29from reflib import logDiag, logWarn, logErr, setLogFile
30from reg import Registry
31from validitygenerator import ValidityOutputGenerator
32from apiconventions import APIConventions
33
34# Simple timer functions
35startTime = None
36
37
38def startTimer(timeit):
39    global startTime
40    if timeit:
41        startTime = time.process_time()
42
43
44def endTimer(timeit, msg):
45    global startTime
46    if timeit and startTime is not None:
47        endTime = time.process_time()
48        logDiag(msg, endTime - startTime)
49        startTime = None
50
51
52def makeREstring(strings, default=None, strings_are_regex=False):
53    """Turn a list of strings into a regexp string matching exactly those strings."""
54    if strings or default is None:
55        if not strings_are_regex:
56            strings = (re.escape(s) for s in strings)
57        return '^(' + '|'.join(strings) + ')$'
58    return default
59
60
61def makeGenOpts(args):
62    """Returns a directory of [ generator function, generator options ] indexed
63    by specified short names. The generator options incorporate the following
64    parameters:
65
66    args is an parsed argument object; see below for the fields that are used."""
67    global genOpts
68    genOpts = {}
69
70    # Default class of extensions to include, or None
71    defaultExtensions = args.defaultExtensions
72
73    # Additional extensions to include (list of extensions)
74    extensions = args.extension
75
76    # Extensions to remove (list of extensions)
77    removeExtensions = args.removeExtensions
78
79    # Extensions to emit (list of extensions)
80    emitExtensions = args.emitExtensions
81
82    # SPIR-V capabilities / features to emit (list of extensions & capabilities)
83    emitSpirv = args.emitSpirv
84
85    # Vulkan Formats to emit
86    emitFormats = args.emitFormats
87
88    # Features to include (list of features)
89    features = args.feature
90
91    # Whether to disable inclusion protect in headers
92    protect = args.protect
93
94    # Output target directory
95    directory = args.directory
96
97    # Path to generated files, particularly apimap.py
98    genpath = args.genpath
99
100    # Generate MISRA C-friendly headers
101    misracstyle = args.misracstyle;
102
103    # Generate MISRA C++-friendly headers
104    misracppstyle = args.misracppstyle;
105
106    # Descriptive names for various regexp patterns used to select
107    # versions and extensions
108    allFormats = allSpirv = allFeatures = allExtensions = r'.*'
109
110    # Turn lists of names/patterns into matching regular expressions
111    addExtensionsPat     = makeREstring(extensions, None)
112    removeExtensionsPat  = makeREstring(removeExtensions, None)
113    emitExtensionsPat    = makeREstring(emitExtensions, allExtensions)
114    emitSpirvPat         = makeREstring(emitSpirv, allSpirv)
115    emitFormatsPat       = makeREstring(emitFormats, allFormats)
116    featuresPat          = makeREstring(features, allFeatures)
117
118    # Copyright text prefixing all headers (list of strings).
119    # The SPDX formatting below works around constraints of the 'reuse' tool
120    prefixStrings = [
121        '/*',
122        '** Copyright 2015-2022 The Khronos Group Inc.',
123        '**',
124        '** SPDX-License-Identifier' + ': Apache-2.0',
125        '*/',
126        ''
127    ]
128
129    # Text specific to Vulkan headers
130    vkPrefixStrings = [
131        '/*',
132        '** This header is generated from the Khronos Vulkan XML API Registry.',
133        '**',
134        '*/',
135        ''
136    ]
137
138    # Defaults for generating re-inclusion protection wrappers (or not)
139    protectFile = protect
140
141    # An API style conventions object
142    conventions = APIConventions()
143
144    defaultAPIName = conventions.xml_api_name
145
146    # API include files for spec and ref pages
147    # Overwrites include subdirectories in spec source tree
148    # The generated include files do not include the calling convention
149    # macros (apientry etc.), unlike the header files.
150    # Because the 1.0 core branch includes ref pages for extensions,
151    # all the extension interfaces need to be generated, even though
152    # none are used by the core spec itself.
153    genOpts['apiinc'] = [
154          DocOutputGenerator,
155          DocGeneratorOptions(
156            conventions       = conventions,
157            filename          = 'timeMarker',
158            directory         = directory,
159            genpath           = genpath,
160            apiname           = defaultAPIName,
161            profile           = None,
162            versions          = featuresPat,
163            emitversions      = featuresPat,
164            defaultExtensions = None,
165            addExtensions     = addExtensionsPat,
166            removeExtensions  = removeExtensionsPat,
167            emitExtensions    = emitExtensionsPat,
168            prefixText        = prefixStrings + vkPrefixStrings,
169            apicall           = '',
170            apientry          = '',
171            apientryp         = '*',
172            alignFuncParam    = 48,
173            expandEnumerants  = False)
174        ]
175
176    # Python and Ruby representations of API information, used by scripts
177    # that do not need to load the full XML.
178    genOpts['apimap.py'] = [
179          PyOutputGenerator,
180          DocGeneratorOptions(
181            conventions       = conventions,
182            filename          = 'apimap.py',
183            directory         = directory,
184            genpath           = None,
185            apiname           = defaultAPIName,
186            profile           = None,
187            versions          = featuresPat,
188            emitversions      = featuresPat,
189            defaultExtensions = None,
190            addExtensions     = addExtensionsPat,
191            removeExtensions  = removeExtensionsPat,
192            emitExtensions    = emitExtensionsPat,
193            reparentEnums     = False)
194        ]
195
196    genOpts['apimap.rb'] = [
197          RubyOutputGenerator,
198          DocGeneratorOptions(
199            conventions       = conventions,
200            filename          = 'apimap.rb',
201            directory         = directory,
202            genpath           = None,
203            apiname           = defaultAPIName,
204            profile           = None,
205            versions          = featuresPat,
206            emitversions      = featuresPat,
207            defaultExtensions = None,
208            addExtensions     = addExtensionsPat,
209            removeExtensions  = removeExtensionsPat,
210            emitExtensions    = emitExtensionsPat,
211            reparentEnums     = False)
212        ]
213
214
215    # API validity files for spec
216    #
217    # requireCommandAliases is set to True because we need validity files
218    # for the command something is promoted to even when the promoted-to
219    # feature is not included. This avoids wordy includes of validity files.
220    genOpts['validinc'] = [
221          ValidityOutputGenerator,
222          DocGeneratorOptions(
223            conventions       = conventions,
224            filename          = 'timeMarker',
225            directory         = directory,
226            genpath           = None,
227            apiname           = defaultAPIName,
228            profile           = None,
229            versions          = featuresPat,
230            emitversions      = featuresPat,
231            defaultExtensions = None,
232            addExtensions     = addExtensionsPat,
233            removeExtensions  = removeExtensionsPat,
234            emitExtensions    = emitExtensionsPat,
235            requireCommandAliases = True,
236            )
237        ]
238
239    # API host sync table files for spec
240    genOpts['hostsyncinc'] = [
241          HostSynchronizationOutputGenerator,
242          DocGeneratorOptions(
243            conventions       = conventions,
244            filename          = 'timeMarker',
245            directory         = directory,
246            genpath           = None,
247            apiname           = defaultAPIName,
248            profile           = None,
249            versions          = featuresPat,
250            emitversions      = featuresPat,
251            defaultExtensions = None,
252            addExtensions     = addExtensionsPat,
253            removeExtensions  = removeExtensionsPat,
254            emitExtensions    = emitExtensionsPat,
255            reparentEnums     = False)
256        ]
257
258    # Extension metainformation for spec extension appendices
259    # Includes all extensions by default, but only so that the generated
260    # 'promoted_extensions_*' files refer to all extensions that were
261    # promoted to a core version.
262    genOpts['extinc'] = [
263          ExtensionMetaDocOutputGenerator,
264          ExtensionMetaDocGeneratorOptions(
265            conventions       = conventions,
266            filename          = 'timeMarker',
267            directory         = directory,
268            genpath           = None,
269            apiname           = defaultAPIName,
270            profile           = None,
271            versions          = featuresPat,
272            emitversions      = None,
273            defaultExtensions = defaultExtensions,
274            addExtensions     = addExtensionsPat,
275            removeExtensions  = None,
276            emitExtensions    = emitExtensionsPat)
277        ]
278
279    # Version and extension interface docs for version/extension appendices
280    # Includes all extensions by default.
281    genOpts['interfaceinc'] = [
282          InterfaceDocGenerator,
283          DocGeneratorOptions(
284            conventions       = conventions,
285            filename          = 'timeMarker',
286            directory         = directory,
287            genpath           = None,
288            apiname           = defaultAPIName,
289            profile           = None,
290            versions          = featuresPat,
291            emitversions      = featuresPat,
292            defaultExtensions = None,
293            addExtensions     = addExtensionsPat,
294            removeExtensions  = removeExtensionsPat,
295            emitExtensions    = emitExtensionsPat,
296            reparentEnums     = False)
297        ]
298
299    genOpts['spirvcapinc'] = [
300          SpirvCapabilityOutputGenerator,
301          DocGeneratorOptions(
302            conventions       = conventions,
303            filename          = 'timeMarker',
304            directory         = directory,
305            genpath           = None,
306            apiname           = defaultAPIName,
307            profile           = None,
308            versions          = featuresPat,
309            emitversions      = featuresPat,
310            defaultExtensions = None,
311            addExtensions     = addExtensionsPat,
312            removeExtensions  = removeExtensionsPat,
313            emitExtensions    = emitExtensionsPat,
314            emitSpirv         = emitSpirvPat,
315            reparentEnums     = False)
316        ]
317
318    # Used to generate various format chapter tables
319    genOpts['formatsinc'] = [
320          FormatsOutputGenerator,
321          DocGeneratorOptions(
322            conventions       = conventions,
323            filename          = 'timeMarker',
324            directory         = directory,
325            genpath           = None,
326            apiname           = defaultAPIName,
327            profile           = None,
328            versions          = featuresPat,
329            emitversions      = featuresPat,
330            defaultExtensions = None,
331            addExtensions     = addExtensionsPat,
332            removeExtensions  = removeExtensionsPat,
333            emitExtensions    = emitExtensionsPat,
334            emitFormats       = emitFormatsPat,
335            reparentEnums     = False)
336        ]
337
338    # Platform extensions, in their own header files
339    # Each element of the platforms[] array defines information for
340    # generating a single platform:
341    #   [0] is the generated header file name
342    #   [1] is the set of platform extensions to generate
343    #   [2] is additional extensions whose interfaces should be considered,
344    #   but suppressed in the output, to avoid duplicate definitions of
345    #   dependent types like VkDisplayKHR and VkSurfaceKHR which come from
346    #   non-platform extensions.
347
348    # Track all platform extensions, for exclusion from vulkan_core.h
349    allPlatformExtensions = []
350
351    # Extensions suppressed for all WSI platforms (WSI extensions required
352    # by all platforms)
353    commonSuppressExtensions = [ 'VK_KHR_display', 'VK_KHR_swapchain' ]
354
355    # Extensions required and suppressed for beta "platform". This can
356    # probably eventually be derived from the requires= attributes of
357    # the extension blocks.
358    betaRequireExtensions = [
359        'VK_KHR_portability_subset',
360        'VK_KHR_video_encode_queue',
361        'VK_EXT_video_encode_h264',
362        'VK_EXT_video_encode_h265',
363    ]
364
365    betaSuppressExtensions = [
366        'VK_KHR_video_queue'
367    ]
368
369    platforms = [
370        [ 'vulkan_android.h',     [ 'VK_KHR_android_surface',
371                                    'VK_ANDROID_external_memory_android_hardware_buffer'
372                                                                  ], commonSuppressExtensions +
373                                                                     [ 'VK_KHR_format_feature_flags2',
374                                                                     ] ],
375        [ 'vulkan_fuchsia.h',     [ 'VK_FUCHSIA_imagepipe_surface',
376                                    'VK_FUCHSIA_external_memory',
377                                    'VK_FUCHSIA_external_semaphore',
378                                    'VK_FUCHSIA_buffer_collection' ], commonSuppressExtensions ],
379        [ 'vulkan_ggp.h',         [ 'VK_GGP_stream_descriptor_surface',
380                                    'VK_GGP_frame_token'          ], commonSuppressExtensions ],
381        [ 'vulkan_ios.h',         [ 'VK_MVK_ios_surface'          ], commonSuppressExtensions ],
382        [ 'vulkan_macos.h',       [ 'VK_MVK_macos_surface'        ], commonSuppressExtensions ],
383        [ 'vulkan_vi.h',          [ 'VK_NN_vi_surface'            ], commonSuppressExtensions ],
384        [ 'vulkan_wayland.h',     [ 'VK_KHR_wayland_surface'      ], commonSuppressExtensions ],
385        [ 'vulkan_win32.h',       [ 'VK_.*_win32(|_.*)', 'VK_.*_winrt(|_.*)', 'VK_EXT_full_screen_exclusive' ],
386                                                                     commonSuppressExtensions +
387                                                                     [ 'VK_KHR_external_semaphore',
388                                                                       'VK_KHR_external_memory_capabilities',
389                                                                       'VK_KHR_external_fence',
390                                                                       'VK_KHR_external_fence_capabilities',
391                                                                       'VK_KHR_get_surface_capabilities2',
392                                                                       'VK_NV_external_memory_capabilities',
393                                                                     ] ],
394        [ 'vulkan_xcb.h',         [ 'VK_KHR_xcb_surface'          ], commonSuppressExtensions ],
395        [ 'vulkan_xlib.h',        [ 'VK_KHR_xlib_surface'         ], commonSuppressExtensions ],
396        [ 'vulkan_directfb.h',    [ 'VK_EXT_directfb_surface'     ], commonSuppressExtensions ],
397        [ 'vulkan_xlib_xrandr.h', [ 'VK_EXT_acquire_xlib_display' ], commonSuppressExtensions ],
398        [ 'vulkan_metal.h',       [ 'VK_EXT_metal_surface',
399                                    'VK_EXT_metal_objects'        ], commonSuppressExtensions ],
400        [ 'vulkan_screen.h',      [ 'VK_QNX_screen_surface'       ], commonSuppressExtensions ],
401        [ 'vulkan_beta.h',        betaRequireExtensions,             betaSuppressExtensions ],
402    ]
403
404    for platform in platforms:
405        headername = platform[0]
406
407        allPlatformExtensions += platform[1]
408
409        addPlatformExtensionsRE = makeREstring(
410            platform[1] + platform[2], strings_are_regex=True)
411        emitPlatformExtensionsRE = makeREstring(
412            platform[1], strings_are_regex=True)
413
414        opts = CGeneratorOptions(
415            conventions       = conventions,
416            filename          = headername,
417            directory         = directory,
418            genpath           = None,
419            apiname           = defaultAPIName,
420            profile           = None,
421            versions          = featuresPat,
422            emitversions      = None,
423            defaultExtensions = None,
424            addExtensions     = addPlatformExtensionsRE,
425            removeExtensions  = None,
426            emitExtensions    = emitPlatformExtensionsRE,
427            prefixText        = prefixStrings + vkPrefixStrings,
428            genFuncPointers   = True,
429            protectFile       = protectFile,
430            protectFeature    = False,
431            protectProto      = '#ifndef',
432            protectProtoStr   = 'VK_NO_PROTOTYPES',
433            apicall           = 'VKAPI_ATTR ',
434            apientry          = 'VKAPI_CALL ',
435            apientryp         = 'VKAPI_PTR *',
436            alignFuncParam    = 48,
437            misracstyle       = misracstyle,
438            misracppstyle     = misracppstyle)
439
440        genOpts[headername] = [ COutputGenerator, opts ]
441
442    # Header for core API + extensions.
443    # To generate just the core API,
444    # change to 'defaultExtensions = None' below.
445    #
446    # By default this adds all enabled, non-platform extensions.
447    # It removes all platform extensions (from the platform headers options
448    # constructed above) as well as any explicitly specified removals.
449
450    removeExtensionsPat = makeREstring(
451        allPlatformExtensions + removeExtensions, None, strings_are_regex=True)
452
453    genOpts['vulkan_core.h'] = [
454          COutputGenerator,
455          CGeneratorOptions(
456            conventions       = conventions,
457            filename          = 'vulkan_core.h',
458            directory         = directory,
459            genpath           = None,
460            apiname           = defaultAPIName,
461            profile           = None,
462            versions          = featuresPat,
463            emitversions      = featuresPat,
464            defaultExtensions = defaultExtensions,
465            addExtensions     = addExtensionsPat,
466            removeExtensions  = removeExtensionsPat,
467            emitExtensions    = emitExtensionsPat,
468            prefixText        = prefixStrings + vkPrefixStrings,
469            genFuncPointers   = True,
470            protectFile       = protectFile,
471            protectFeature    = False,
472            protectProto      = '#ifndef',
473            protectProtoStr   = 'VK_NO_PROTOTYPES',
474            apicall           = 'VKAPI_ATTR ',
475            apientry          = 'VKAPI_CALL ',
476            apientryp         = 'VKAPI_PTR *',
477            alignFuncParam    = 48,
478            misracstyle       = misracstyle,
479            misracppstyle     = misracppstyle)
480        ]
481
482    # Unused - vulkan10.h target.
483    # It is possible to generate a header with just the Vulkan 1.0 +
484    # extension interfaces defined, but since the promoted KHR extensions
485    # are now defined in terms of the 1.1 interfaces, such a header is very
486    # similar to vulkan_core.h.
487    genOpts['vulkan10.h'] = [
488          COutputGenerator,
489          CGeneratorOptions(
490            conventions       = conventions,
491            filename          = 'vulkan10.h',
492            directory         = directory,
493            genpath           = None,
494            apiname           = defaultAPIName,
495            profile           = None,
496            versions          = 'VK_VERSION_1_0',
497            emitversions      = 'VK_VERSION_1_0',
498            defaultExtensions = None,
499            addExtensions     = None,
500            removeExtensions  = None,
501            emitExtensions    = None,
502            prefixText        = prefixStrings + vkPrefixStrings,
503            genFuncPointers   = True,
504            protectFile       = protectFile,
505            protectFeature    = False,
506            protectProto      = '#ifndef',
507            protectProtoStr   = 'VK_NO_PROTOTYPES',
508            apicall           = 'VKAPI_ATTR ',
509            apientry          = 'VKAPI_CALL ',
510            apientryp         = 'VKAPI_PTR *',
511            alignFuncParam    = 48,
512            misracstyle       = misracstyle,
513            misracppstyle     = misracppstyle)
514        ]
515
516    # Video header target - combines all video extension dependencies into a
517    # single header, at present.
518    genOpts['vk_video.h'] = [
519          COutputGenerator,
520          CGeneratorOptions(
521            conventions       = conventions,
522            filename          = 'vk_video.h',
523            directory         = directory,
524            genpath           = None,
525            apiname           = 'vulkan',
526            profile           = None,
527            versions          = None,
528            emitversions      = None,
529            defaultExtensions = defaultExtensions,
530            addExtensions     = addExtensionsPat,
531            removeExtensions  = removeExtensionsPat,
532            emitExtensions    = emitExtensionsPat,
533            prefixText        = prefixStrings + vkPrefixStrings,
534            genFuncPointers   = True,
535            protectFile       = protectFile,
536            protectFeature    = False,
537            protectProto      = '#ifndef',
538            protectProtoStr   = 'VK_NO_PROTOTYPES',
539            apicall           = '',
540            apientry          = '',
541            apientryp         = '',
542            alignFuncParam    = 48,
543            misracstyle       = misracstyle,
544            misracppstyle     = misracppstyle)
545    ]
546
547    # Video extension 'Std' interfaces, each in its own header files
548    # These are not Vulkan extensions, or a part of the Vulkan API at all,
549    # but are treated in a similar fashion for generation purposes.
550    #
551    # Each element of the videoStd[] array is an extension name defining an
552    # interface, and is also the basis for the generated header file name.
553
554    videoStd = [
555        'vulkan_video_codecs_common',
556        'vulkan_video_codec_h264std',
557        'vulkan_video_codec_h264std_decode',
558        'vulkan_video_codec_h264std_encode',
559        'vulkan_video_codec_h265std',
560        'vulkan_video_codec_h265std_decode',
561        'vulkan_video_codec_h265std_encode',
562    ]
563
564    addExtensionRE = makeREstring(videoStd)
565    for codec in videoStd:
566        headername = f'{codec}.h'
567
568        # Consider all of the codecs 'extensions', but only emit this one
569        emitExtensionRE = makeREstring([codec])
570
571        opts = CGeneratorOptions(
572            conventions       = conventions,
573            filename          = headername,
574            directory         = directory,
575            genpath           = None,
576            apiname           = defaultAPIName,
577            profile           = None,
578            versions          = None,
579            emitversions      = None,
580            defaultExtensions = None,
581            addExtensions     = addExtensionRE,
582            removeExtensions  = None,
583            emitExtensions    = emitExtensionRE,
584            prefixText        = prefixStrings + vkPrefixStrings,
585            genFuncPointers   = False,
586            protectFile       = protectFile,
587            protectFeature    = False,
588            alignFuncParam    = 48,
589            )
590
591        genOpts[headername] = [ COutputGenerator, opts ]
592
593    # Unused - vulkan11.h target.
594    # It is possible to generate a header with just the Vulkan 1.0 +
595    # extension interfaces defined, but since the promoted KHR extensions
596    # are now defined in terms of the 1.1 interfaces, such a header is very
597    # similar to vulkan_core.h.
598    genOpts['vulkan11.h'] = [
599          COutputGenerator,
600          CGeneratorOptions(
601            conventions       = conventions,
602            filename          = 'vulkan11.h',
603            directory         = directory,
604            genpath           = None,
605            apiname           = defaultAPIName,
606            profile           = None,
607            versions          = '^VK_VERSION_1_[01]$',
608            emitversions      = '^VK_VERSION_1_[01]$',
609            defaultExtensions = None,
610            addExtensions     = None,
611            removeExtensions  = None,
612            emitExtensions    = None,
613            prefixText        = prefixStrings + vkPrefixStrings,
614            genFuncPointers   = True,
615            protectFile       = protectFile,
616            protectFeature    = False,
617            protectProto      = '#ifndef',
618            protectProtoStr   = 'VK_NO_PROTOTYPES',
619            apicall           = 'VKAPI_ATTR ',
620            apientry          = 'VKAPI_CALL ',
621            apientryp         = 'VKAPI_PTR *',
622            alignFuncParam    = 48,
623            misracstyle       = misracstyle,
624            misracppstyle     = misracppstyle)
625        ]
626
627    genOpts['alias.h'] = [
628          COutputGenerator,
629          CGeneratorOptions(
630            conventions       = conventions,
631            filename          = 'alias.h',
632            directory         = directory,
633            genpath           = None,
634            apiname           = defaultAPIName,
635            profile           = None,
636            versions          = featuresPat,
637            emitversions      = featuresPat,
638            defaultExtensions = defaultExtensions,
639            addExtensions     = None,
640            removeExtensions  = removeExtensionsPat,
641            emitExtensions    = emitExtensionsPat,
642            prefixText        = None,
643            genFuncPointers   = False,
644            protectFile       = False,
645            protectFeature    = False,
646            protectProto      = '',
647            protectProtoStr   = '',
648            apicall           = '',
649            apientry          = '',
650            apientryp         = '',
651            alignFuncParam    = 36)
652        ]
653
654
655def genTarget(args):
656    """Create an API generator and corresponding generator options based on
657    the requested target and command line options.
658
659    This is encapsulated in a function so it can be profiled and/or timed.
660    The args parameter is an parsed argument object containing the following
661    fields that are used:
662
663    - target - target to generate
664    - directory - directory to generate it in
665    - protect - True if re-inclusion wrappers should be created
666    - extensions - list of additional extensions to include in generated interfaces"""
667
668    # Create generator options with parameters specified on command line
669    makeGenOpts(args)
670
671    # Select a generator matching the requested target
672    if args.target in genOpts:
673        createGenerator = genOpts[args.target][0]
674        options = genOpts[args.target][1]
675
676        logDiag('* Building', options.filename)
677        logDiag('* options.versions          =', options.versions)
678        logDiag('* options.emitversions      =', options.emitversions)
679        logDiag('* options.defaultExtensions =', options.defaultExtensions)
680        logDiag('* options.addExtensions     =', options.addExtensions)
681        logDiag('* options.removeExtensions  =', options.removeExtensions)
682        logDiag('* options.emitExtensions    =', options.emitExtensions)
683        logDiag('* options.emitSpirv         =', options.emitSpirv)
684        logDiag('* options.emitFormats       =', options.emitFormats)
685
686        gen = createGenerator(errFile=errWarn,
687                              warnFile=errWarn,
688                              diagFile=diag)
689        return (gen, options)
690    else:
691        logErr('No generator options for unknown target:', args.target)
692        return None
693
694
695# -feature name
696# -extension name
697# For both, "name" may be a single name, or a space-separated list
698# of names, or a regular expression.
699if __name__ == '__main__':
700    parser = argparse.ArgumentParser()
701
702    parser.add_argument('-defaultExtensions', action='store',
703                        default=APIConventions().xml_api_name,
704                        help='Specify a single class of extensions to add to targets')
705    parser.add_argument('-extension', action='append',
706                        default=[],
707                        help='Specify an extension or extensions to add to targets')
708    parser.add_argument('-removeExtensions', action='append',
709                        default=[],
710                        help='Specify an extension or extensions to remove from targets')
711    parser.add_argument('-emitExtensions', action='append',
712                        default=[],
713                        help='Specify an extension or extensions to emit in targets')
714    parser.add_argument('-emitSpirv', action='append',
715                        default=[],
716                        help='Specify a SPIR-V extension or capability to emit in targets')
717    parser.add_argument('-emitFormats', action='append',
718                        default=[],
719                        help='Specify Vulkan Formats to emit in targets')
720    parser.add_argument('-feature', action='append',
721                        default=[],
722                        help='Specify a core API feature name or names to add to targets')
723    parser.add_argument('-debug', action='store_true',
724                        help='Enable debugging')
725    parser.add_argument('-dump', action='store_true',
726                        help='Enable dump to stderr')
727    parser.add_argument('-diagfile', action='store',
728                        default=None,
729                        help='Write diagnostics to specified file')
730    parser.add_argument('-errfile', action='store',
731                        default=None,
732                        help='Write errors and warnings to specified file instead of stderr')
733    parser.add_argument('-noprotect', dest='protect', action='store_false',
734                        help='Disable inclusion protection in output headers')
735    parser.add_argument('-profile', action='store_true',
736                        help='Enable profiling')
737    parser.add_argument('-registry', action='store',
738                        default='vk.xml',
739                        help='Use specified registry file instead of vk.xml')
740    parser.add_argument('-time', action='store_true',
741                        help='Enable timing')
742    parser.add_argument('-genpath', action='store', default='gen',
743                        help='Path to generated files')
744    parser.add_argument('-o', action='store', dest='directory',
745                        default='.',
746                        help='Create target and related files in specified directory')
747    parser.add_argument('target', metavar='target', nargs='?',
748                        help='Specify target')
749    parser.add_argument('-quiet', action='store_true', default=True,
750                        help='Suppress script output during normal execution.')
751    parser.add_argument('-verbose', action='store_false', dest='quiet', default=True,
752                        help='Enable script output during normal execution.')
753    parser.add_argument('-misracstyle', dest='misracstyle', action='store_true',
754                        help='generate MISRA C-friendly headers')
755    parser.add_argument('-misracppstyle', dest='misracppstyle', action='store_true',
756                        help='generate MISRA C++-friendly headers')
757
758    args = parser.parse_args()
759
760    # This splits arguments which are space-separated lists
761    args.feature = [name for arg in args.feature for name in arg.split()]
762    args.extension = [name for arg in args.extension for name in arg.split()]
763
764    # create error/warning & diagnostic files
765    if args.errfile:
766        errWarn = open(args.errfile, 'w', encoding='utf-8')
767    else:
768        errWarn = sys.stderr
769
770    if args.diagfile:
771        diag = open(args.diagfile, 'w', encoding='utf-8')
772    else:
773        diag = None
774
775    if args.time:
776        # Log diagnostics and warnings
777        setLogFile(setDiag = True, setWarn = True, filename = '-')
778
779    # Create the API generator & generator options
780    (gen, options) = genTarget(args)
781
782    # Create the registry object with the specified generator and generator
783    # options. The options are set before XML loading as they may affect it.
784    reg = Registry(gen, options)
785
786    # Parse the specified registry XML into an ElementTree object
787    startTimer(args.time)
788    tree = etree.parse(args.registry)
789    endTimer(args.time, '* Time to make ElementTree =')
790
791    # Load the XML tree into the registry object
792    startTimer(args.time)
793    reg.loadElementTree(tree)
794    endTimer(args.time, '* Time to parse ElementTree =')
795
796    if args.dump:
797        logDiag('* Dumping registry to regdump.txt')
798        reg.dumpReg(filehandle=open('regdump.txt', 'w', encoding='utf-8'))
799
800    # Finally, use the output generator to create the requested target
801    if args.debug:
802        pdb.run('reg.apiGen()')
803    else:
804        startTimer(args.time)
805        reg.apiGen()
806        endTimer(args.time, '* Time to generate ' + options.filename + ' =')
807
808    if not args.quiet:
809        logDiag('* Generated', options.filename)
810