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