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