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