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