• 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        [ 'vulkan_ohos.h',        [ 'VK_OpenHarmony_OHOS_surface',
401                                    'VK_OpenHarmony_external_memory_ohos_native_buffer'
402                                                                  ], commonSuppressExtensions +
403                                                                      [ 'VK_KHR_format_feature_flags2',
404                                                                      ] ],
405    ]
406
407    for platform in platforms:
408        headername = platform[0]
409
410        allPlatformExtensions += platform[1]
411
412        addPlatformExtensionsRE = makeREstring(
413            platform[1] + platform[2], strings_are_regex=True)
414        emitPlatformExtensionsRE = makeREstring(
415            platform[1], strings_are_regex=True)
416
417        opts = CGeneratorOptions(
418            conventions       = conventions,
419            filename          = headername,
420            directory         = directory,
421            genpath           = None,
422            apiname           = defaultAPIName,
423            profile           = None,
424            versions          = featuresPat,
425            emitversions      = None,
426            defaultExtensions = None,
427            addExtensions     = addPlatformExtensionsRE,
428            removeExtensions  = None,
429            emitExtensions    = emitPlatformExtensionsRE,
430            prefixText        = prefixStrings + vkPrefixStrings,
431            genFuncPointers   = True,
432            protectFile       = protectFile,
433            protectFeature    = False,
434            protectProto      = '#ifndef',
435            protectProtoStr   = 'VK_NO_PROTOTYPES',
436            apicall           = 'VKAPI_ATTR ',
437            apientry          = 'VKAPI_CALL ',
438            apientryp         = 'VKAPI_PTR *',
439            alignFuncParam    = 48,
440            misracstyle       = misracstyle,
441            misracppstyle     = misracppstyle)
442
443        genOpts[headername] = [ COutputGenerator, opts ]
444
445    # Header for core API + extensions.
446    # To generate just the core API,
447    # change to 'defaultExtensions = None' below.
448    #
449    # By default this adds all enabled, non-platform extensions.
450    # It removes all platform extensions (from the platform headers options
451    # constructed above) as well as any explicitly specified removals.
452
453    removeExtensionsPat = makeREstring(
454        allPlatformExtensions + removeExtensions, None, strings_are_regex=True)
455
456    genOpts['vulkan_core.h'] = [
457          COutputGenerator,
458          CGeneratorOptions(
459            conventions       = conventions,
460            filename          = 'vulkan_core.h',
461            directory         = directory,
462            genpath           = None,
463            apiname           = defaultAPIName,
464            profile           = None,
465            versions          = featuresPat,
466            emitversions      = featuresPat,
467            defaultExtensions = defaultExtensions,
468            addExtensions     = addExtensionsPat,
469            removeExtensions  = removeExtensionsPat,
470            emitExtensions    = emitExtensionsPat,
471            prefixText        = prefixStrings + vkPrefixStrings,
472            genFuncPointers   = True,
473            protectFile       = protectFile,
474            protectFeature    = False,
475            protectProto      = '#ifndef',
476            protectProtoStr   = 'VK_NO_PROTOTYPES',
477            apicall           = 'VKAPI_ATTR ',
478            apientry          = 'VKAPI_CALL ',
479            apientryp         = 'VKAPI_PTR *',
480            alignFuncParam    = 48,
481            misracstyle       = misracstyle,
482            misracppstyle     = misracppstyle)
483        ]
484
485    # Unused - vulkan10.h target.
486    # It is possible to generate a header with just the Vulkan 1.0 +
487    # extension interfaces defined, but since the promoted KHR extensions
488    # are now defined in terms of the 1.1 interfaces, such a header is very
489    # similar to vulkan_core.h.
490    genOpts['vulkan10.h'] = [
491          COutputGenerator,
492          CGeneratorOptions(
493            conventions       = conventions,
494            filename          = 'vulkan10.h',
495            directory         = directory,
496            genpath           = None,
497            apiname           = defaultAPIName,
498            profile           = None,
499            versions          = 'VK_VERSION_1_0',
500            emitversions      = 'VK_VERSION_1_0',
501            defaultExtensions = None,
502            addExtensions     = None,
503            removeExtensions  = None,
504            emitExtensions    = None,
505            prefixText        = prefixStrings + vkPrefixStrings,
506            genFuncPointers   = True,
507            protectFile       = protectFile,
508            protectFeature    = False,
509            protectProto      = '#ifndef',
510            protectProtoStr   = 'VK_NO_PROTOTYPES',
511            apicall           = 'VKAPI_ATTR ',
512            apientry          = 'VKAPI_CALL ',
513            apientryp         = 'VKAPI_PTR *',
514            alignFuncParam    = 48,
515            misracstyle       = misracstyle,
516            misracppstyle     = misracppstyle)
517        ]
518
519    # Unused - vulkan11.h target.
520    # It is possible to generate a header with just the Vulkan 1.0 +
521    # extension interfaces defined, but since the promoted KHR extensions
522    # are now defined in terms of the 1.1 interfaces, such a header is very
523    # similar to vulkan_core.h.
524    genOpts['vulkan11.h'] = [
525          COutputGenerator,
526          CGeneratorOptions(
527            conventions       = conventions,
528            filename          = 'vulkan11.h',
529            directory         = directory,
530            genpath           = None,
531            apiname           = defaultAPIName,
532            profile           = None,
533            versions          = '^VK_VERSION_1_[01]$',
534            emitversions      = '^VK_VERSION_1_[01]$',
535            defaultExtensions = None,
536            addExtensions     = None,
537            removeExtensions  = None,
538            emitExtensions    = None,
539            prefixText        = prefixStrings + vkPrefixStrings,
540            genFuncPointers   = True,
541            protectFile       = protectFile,
542            protectFeature    = False,
543            protectProto      = '#ifndef',
544            protectProtoStr   = 'VK_NO_PROTOTYPES',
545            apicall           = 'VKAPI_ATTR ',
546            apientry          = 'VKAPI_CALL ',
547            apientryp         = 'VKAPI_PTR *',
548            alignFuncParam    = 48,
549            misracstyle       = misracstyle,
550            misracppstyle     = misracppstyle)
551        ]
552
553    genOpts['alias.h'] = [
554          COutputGenerator,
555          CGeneratorOptions(
556            conventions       = conventions,
557            filename          = 'alias.h',
558            directory         = directory,
559            genpath           = None,
560            apiname           = defaultAPIName,
561            profile           = None,
562            versions          = featuresPat,
563            emitversions      = featuresPat,
564            defaultExtensions = defaultExtensions,
565            addExtensions     = None,
566            removeExtensions  = removeExtensionsPat,
567            emitExtensions    = emitExtensionsPat,
568            prefixText        = None,
569            genFuncPointers   = False,
570            protectFile       = False,
571            protectFeature    = False,
572            protectProto      = '',
573            protectProtoStr   = '',
574            apicall           = '',
575            apientry          = '',
576            apientryp         = '',
577            alignFuncParam    = 36)
578        ]
579
580
581def genTarget(args):
582    """Create an API generator and corresponding generator options based on
583    the requested target and command line options.
584
585    This is encapsulated in a function so it can be profiled and/or timed.
586    The args parameter is an parsed argument object containing the following
587    fields that are used:
588
589    - target - target to generate
590    - directory - directory to generate it in
591    - protect - True if re-inclusion wrappers should be created
592    - extensions - list of additional extensions to include in generated interfaces"""
593
594    # Create generator options with parameters specified on command line
595    makeGenOpts(args)
596
597    # pdb.set_trace()
598
599    # Select a generator matching the requested target
600    if args.target in genOpts:
601        createGenerator = genOpts[args.target][0]
602        options = genOpts[args.target][1]
603
604        logDiag('* Building', options.filename)
605        logDiag('* options.versions          =', options.versions)
606        logDiag('* options.emitversions      =', options.emitversions)
607        logDiag('* options.defaultExtensions =', options.defaultExtensions)
608        logDiag('* options.addExtensions     =', options.addExtensions)
609        logDiag('* options.removeExtensions  =', options.removeExtensions)
610        logDiag('* options.emitExtensions    =', options.emitExtensions)
611        logDiag('* options.emitSpirv         =', options.emitSpirv)
612        logDiag('* options.emitFormats       =', options.emitFormats)
613
614        gen = createGenerator(errFile=errWarn,
615                              warnFile=errWarn,
616                              diagFile=diag)
617        return (gen, options)
618    else:
619        logErr('No generator options for unknown target:', args.target)
620        return None
621
622
623# -feature name
624# -extension name
625# For both, "name" may be a single name, or a space-separated list
626# of names, or a regular expression.
627if __name__ == '__main__':
628    parser = argparse.ArgumentParser()
629
630    parser.add_argument('-defaultExtensions', action='store',
631                        default=APIConventions().xml_api_name,
632                        help='Specify a single class of extensions to add to targets')
633    parser.add_argument('-extension', action='append',
634                        default=[],
635                        help='Specify an extension or extensions to add to targets')
636    parser.add_argument('-removeExtensions', action='append',
637                        default=[],
638                        help='Specify an extension or extensions to remove from targets')
639    parser.add_argument('-emitExtensions', action='append',
640                        default=[],
641                        help='Specify an extension or extensions to emit in targets')
642    parser.add_argument('-emitSpirv', action='append',
643                        default=[],
644                        help='Specify a SPIR-V extension or capability to emit in targets')
645    parser.add_argument('-emitFormats', action='append',
646                        default=[],
647                        help='Specify Vulkan Formats to emit in targets')
648    parser.add_argument('-feature', action='append',
649                        default=[],
650                        help='Specify a core API feature name or names to add to targets')
651    parser.add_argument('-debug', action='store_true',
652                        help='Enable debugging')
653    parser.add_argument('-dump', action='store_true',
654                        help='Enable dump to stderr')
655    parser.add_argument('-diagfile', action='store',
656                        default=None,
657                        help='Write diagnostics to specified file')
658    parser.add_argument('-errfile', action='store',
659                        default=None,
660                        help='Write errors and warnings to specified file instead of stderr')
661    parser.add_argument('-noprotect', dest='protect', action='store_false',
662                        help='Disable inclusion protection in output headers')
663    parser.add_argument('-profile', action='store_true',
664                        help='Enable profiling')
665    parser.add_argument('-registry', action='store',
666                        default='vk.xml',
667                        help='Use specified registry file instead of vk.xml')
668    parser.add_argument('-time', action='store_true',
669                        help='Enable timing')
670    parser.add_argument('-validate', action='store_true',
671                        help='Validate the registry properties and exit')
672    parser.add_argument('-genpath', action='store', default='gen',
673                        help='Path to generated files')
674    parser.add_argument('-o', action='store', dest='directory',
675                        default='.',
676                        help='Create target and related files in specified directory')
677    parser.add_argument('target', metavar='target', nargs='?',
678                        help='Specify target')
679    parser.add_argument('-quiet', action='store_true', default=True,
680                        help='Suppress script output during normal execution.')
681    parser.add_argument('-verbose', action='store_false', dest='quiet', default=True,
682                        help='Enable script output during normal execution.')
683    parser.add_argument('-misracstyle', dest='misracstyle', action='store_true',
684                        help='generate MISRA C-friendly headers')
685    parser.add_argument('-misracppstyle', dest='misracppstyle', action='store_true',
686                        help='generate MISRA C++-friendly headers')
687
688    args = parser.parse_args()
689
690    # This splits arguments which are space-separated lists
691    args.feature = [name for arg in args.feature for name in arg.split()]
692    args.extension = [name for arg in args.extension for name in arg.split()]
693
694    # create error/warning & diagnostic files
695    if args.errfile:
696        errWarn = open(args.errfile, 'w', encoding='utf-8')
697    else:
698        errWarn = sys.stderr
699
700    if args.diagfile:
701        diag = open(args.diagfile, 'w', encoding='utf-8')
702    else:
703        diag = None
704
705    if args.time:
706        # Log diagnostics and warnings
707        setLogFile(setDiag = True, setWarn = True, filename = '-')
708
709    (gen, options) = (None, None)
710    if not args.validate:
711      # Create the API generator & generator options
712      (gen, options) = genTarget(args)
713
714    # Create the registry object with the specified generator and generator
715    # options. The options are set before XML loading as they may affect it.
716    reg = Registry(gen, options)
717
718    # Parse the specified registry XML into an ElementTree object
719    startTimer(args.time)
720    tree = etree.parse(args.registry)
721    endTimer(args.time, '* Time to make ElementTree =')
722
723    # Load the XML tree into the registry object
724    startTimer(args.time)
725    reg.loadElementTree(tree)
726    endTimer(args.time, '* Time to parse ElementTree =')
727
728    if args.validate:
729        success = reg.validateRegistry()
730        sys.exit(0 if success else 1)
731
732    if args.dump:
733        logDiag('* Dumping registry to regdump.txt')
734        reg.dumpReg(filehandle=open('regdump.txt', 'w', encoding='utf-8'))
735
736    # Finally, use the output generator to create the requested target
737    if args.debug:
738        pdb.run('reg.apiGen()')
739    else:
740        startTimer(args.time)
741        reg.apiGen()
742        endTimer(args.time, '* Time to generate ' + options.filename + ' =')
743
744    if not args.quiet:
745        logDiag('* Generated', options.filename)
746