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