1 #!/usr/bin/env python 2 # 3 # Copyright (c) 2013-2015 The Khronos Group Inc. 4 # 5 # Permission is hereby granted, free of charge, to any person obtaining a 6 # copy of this software and/or associated documentation files (the 7 # "Materials"), to deal in the Materials without restriction, including 8 # without limitation the rights to use, copy, modify, merge, publish, 9 # distribute, sublicense, and/or sell copies of the Materials, and to 10 # permit persons to whom the Materials are furnished to do so, subject to 11 # the following conditions: 12 # 13 # The above copyright notice and this permission notice shall be included 14 # in all copies or substantial portions of the Materials. 15 # 16 # THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 # MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 23 24 import sys, time, pdb, string, cProfile 25 from reg import * 26 from generator import write, CGeneratorOptions, COutputGenerator, DocGeneratorOptions, DocOutputGenerator, PyOutputGenerator, ValidityOutputGenerator, HostSynchronizationOutputGenerator, ThreadGeneratorOptions, ThreadOutputGenerator 27 from generator import ParamCheckerGeneratorOptions, ParamCheckerOutputGenerator 28 29 # debug - start header generation in debugger 30 # dump - dump registry after loading 31 # profile - enable Python profiling 32 # protect - whether to use #ifndef protections 33 # registry <filename> - use specified XML registry instead of gl.xml 34 # target - string name of target header, or all targets if None 35 # timeit - time length of registry loading & header generation 36 # validate - validate return & parameter group tags against <group> 37 debug = False 38 dump = False 39 profile = False 40 protect = True 41 target = None 42 timeit = False 43 validate= False 44 # Default input / log files 45 errFilename = None 46 diagFilename = 'diag.txt' 47 regFilename = 'vk.xml' 48 49 if __name__ == '__main__': 50 i = 1 51 while (i < len(sys.argv)): 52 arg = sys.argv[i] 53 i = i + 1 54 if (arg == '-debug'): 55 write('Enabling debug (-debug)', file=sys.stderr) 56 debug = True 57 elif (arg == '-dump'): 58 write('Enabling dump (-dump)', file=sys.stderr) 59 dump = True 60 elif (arg == '-noprotect'): 61 write('Disabling inclusion protection in output headers', file=sys.stderr) 62 protect = False 63 elif (arg == '-profile'): 64 write('Enabling profiling (-profile)', file=sys.stderr) 65 profile = True 66 elif (arg == '-registry'): 67 regFilename = sys.argv[i] 68 i = i+1 69 write('Using registry ', regFilename, file=sys.stderr) 70 elif (arg == '-time'): 71 write('Enabling timing (-time)', file=sys.stderr) 72 timeit = True 73 elif (arg == '-validate'): 74 write('Enabling group validation (-validate)', file=sys.stderr) 75 validate = True 76 elif (arg[0:1] == '-'): 77 write('Unrecognized argument:', arg, file=sys.stderr) 78 exit(1) 79 else: 80 target = arg 81 write('Using target', target, file=sys.stderr) 82 83 # Simple timer functions 84 startTime = None 85 def startTimer(): 86 global startTime 87 startTime = time.clock() 88 def endTimer(msg): 89 global startTime 90 endTime = time.clock() 91 if (timeit): 92 write(msg, endTime - startTime) 93 startTime = None 94 95 # Load & parse registry 96 reg = Registry() 97 98 startTimer() 99 tree = etree.parse(regFilename) 100 endTimer('Time to make ElementTree =') 101 102 startTimer() 103 reg.loadElementTree(tree) 104 endTimer('Time to parse ElementTree =') 105 106 if (validate): 107 reg.validateGroups() 108 109 if (dump): 110 write('***************************************') 111 write('Performing Registry dump to regdump.txt') 112 write('***************************************') 113 reg.dumpReg(filehandle = open('regdump.txt','w')) 114 115 # Turn a list of strings into a regexp string matching exactly those strings 116 def makeREstring(list): 117 return '^(' + '|'.join(list) + ')$' 118 119 # Descriptive names for various regexp patterns used to select 120 # versions and extensions 121 allVersions = allExtensions = '.*' 122 noVersions = noExtensions = None 123 124 # Copyright text prefixing all headers (list of strings). 125 prefixStrings = [ 126 '/*', 127 '** Copyright (c) 2015 The Khronos Group Inc.', 128 '**', 129 '** Permission is hereby granted, free of charge, to any person obtaining a', 130 '** copy of this software and/or associated documentation files (the', 131 '** "Materials"), to deal in the Materials without restriction, including', 132 '** without limitation the rights to use, copy, modify, merge, publish,', 133 '** distribute, sublicense, and/or sell copies of the Materials, and to', 134 '** permit persons to whom the Materials are furnished to do so, subject to', 135 '** the following conditions:', 136 '**', 137 '** The above copyright notice and this permission notice shall be included', 138 '** in all copies or substantial portions of the Materials.', 139 '**', 140 '** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,', 141 '** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF', 142 '** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.', 143 '** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY', 144 '** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,', 145 '** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE', 146 '** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.', 147 '*/', 148 '' 149 ] 150 151 # Text specific to Vulkan headers 152 vkPrefixStrings = [ 153 '/*', 154 '** This header is generated from the Khronos Vulkan XML API Registry.', 155 '**', 156 '*/', 157 '' 158 ] 159 160 # Defaults for generating re-inclusion protection wrappers (or not) 161 protectFile = protect 162 protectFeature = protect 163 protectProto = protect 164 165 buildList = [ 166 # Vulkan 1.0 - core API + extensions. To generate just the core API, 167 # change to 'defaultExtensions = None' below. 168 [ COutputGenerator, 169 CGeneratorOptions( 170 filename = 'include/vulkan/vulkan.h', 171 apiname = 'vulkan', 172 profile = None, 173 versions = allVersions, 174 emitversions = allVersions, 175 defaultExtensions = 'vulkan', 176 addExtensions = None, 177 removeExtensions = None, 178 prefixText = prefixStrings + vkPrefixStrings, 179 genFuncPointers = True, 180 protectFile = protectFile, 181 protectFeature = False, 182 protectProto = '#ifndef', 183 protectProtoStr = 'VK_NO_PROTOTYPES', 184 apicall = 'VKAPI_ATTR ', 185 apientry = 'VKAPI_CALL ', 186 apientryp = 'VKAPI_PTR *', 187 alignFuncParam = 48) 188 ], 189 # Vulkan 1.0 draft - core API include files for spec 190 # Overwrites include subdirectories in spec source tree 191 # The generated include files do not include the calling convention 192 # macros (apientry etc.), unlike the header files. 193 [ DocOutputGenerator, 194 DocGeneratorOptions( 195 filename = 'vulkan-docs', 196 apiname = 'vulkan', 197 profile = None, 198 versions = allVersions, 199 emitversions = allVersions, 200 defaultExtensions = 'vulkan', 201 addExtensions = None, 202 removeExtensions = None, 203 prefixText = prefixStrings + vkPrefixStrings, 204 apicall = '', 205 apientry = '', 206 apientryp = '*', 207 genDirectory = '../../doc/specs/vulkan', 208 alignFuncParam = 48, 209 expandEnumerants = False) 210 ], 211 # Vulkan 1.0 draft - API names to validate man/api spec includes & links 212 # filename = 'vkapi.py', 213 [ PyOutputGenerator, 214 DocGeneratorOptions( 215 filename = '../../doc/specs/vulkan/vkapi.py', 216 apiname = 'vulkan', 217 profile = None, 218 versions = allVersions, 219 emitversions = allVersions, 220 defaultExtensions = None, 221 addExtensions = None, 222 removeExtensions = None) 223 ], 224 # Vulkan 1.0 draft - core API include files for spec 225 # Overwrites include subdirectories in spec source tree 226 [ ValidityOutputGenerator, 227 DocGeneratorOptions( 228 filename = 'validity', 229 apiname = 'vulkan', 230 profile = None, 231 versions = allVersions, 232 emitversions = allVersions, 233 defaultExtensions = None, 234 addExtensions = None, 235 removeExtensions = None, 236 genDirectory = '../../doc/specs/vulkan') 237 ], 238 # Vulkan 1.0 draft - core API include files for spec 239 # Overwrites include subdirectories in spec source tree 240 [ HostSynchronizationOutputGenerator, 241 DocGeneratorOptions( 242 filename = 'hostsynctable', 243 apiname = 'vulkan', 244 profile = None, 245 versions = allVersions, 246 emitversions = allVersions, 247 defaultExtensions = None, 248 addExtensions = None, 249 removeExtensions = None, 250 genDirectory = '../../doc/specs/vulkan') 251 ], 252 # Vulkan 1.0 draft - thread checking layer 253 [ ThreadOutputGenerator, 254 ThreadGeneratorOptions( 255 filename = 'thread_check.h', 256 apiname = 'vulkan', 257 profile = None, 258 versions = allVersions, 259 emitversions = allVersions, 260 defaultExtensions = 'vulkan', 261 addExtensions = None, 262 removeExtensions = None, 263 prefixText = prefixStrings + vkPrefixStrings, 264 genFuncPointers = True, 265 protectFile = protectFile, 266 protectFeature = False, 267 protectProto = True, 268 protectProtoStr = 'VK_PROTOTYPES', 269 apicall = '', 270 apientry = 'VKAPI_CALL ', 271 apientryp = 'VKAPI_PTR *', 272 alignFuncParam = 48) 273 ], 274 [ ParamCheckerOutputGenerator, 275 ParamCheckerGeneratorOptions( 276 filename = 'parameter_validation.h', 277 apiname = 'vulkan', 278 profile = None, 279 versions = allVersions, 280 emitversions = allVersions, 281 defaultExtensions = 'vulkan', 282 addExtensions = None, 283 removeExtensions = None, 284 prefixText = prefixStrings + vkPrefixStrings, 285 genFuncPointers = True, 286 protectFile = protectFile, 287 protectFeature = False, 288 protectProto = None, 289 protectProtoStr = 'VK_NO_PROTOTYPES', 290 apicall = 'VKAPI_ATTR ', 291 apientry = 'VKAPI_CALL ', 292 apientryp = 'VKAPI_PTR *', 293 alignFuncParam = 48) 294 ], 295 None 296 ] 297 298 # create error/warning & diagnostic files 299 if (errFilename): 300 errWarn = open(errFilename,'w') 301 else: 302 errWarn = sys.stderr 303 diag = open(diagFilename, 'w') 304 305 def genHeaders(): 306 # Loop over targets, building each 307 generated = 0 308 for item in buildList: 309 if (item == None): 310 break 311 createGenerator = item[0] 312 genOpts = item[1] 313 if (target and target != genOpts.filename): 314 # write('*** Skipping', genOpts.filename) 315 continue 316 write('*** Building', genOpts.filename) 317 generated = generated + 1 318 startTimer() 319 gen = createGenerator(errFile=errWarn, 320 warnFile=errWarn, 321 diagFile=diag) 322 reg.setGenerator(gen) 323 reg.apiGen(genOpts) 324 write('** Generated', genOpts.filename) 325 endTimer('Time to generate ' + genOpts.filename + ' =') 326 if (target and generated == 0): 327 write('Failed to generate target:', target) 328 329 if (debug): 330 pdb.run('genHeaders()') 331 elif (profile): 332 import cProfile, pstats 333 cProfile.run('genHeaders()', 'profile.txt') 334 p = pstats.Stats('profile.txt') 335 p.strip_dirs().sort_stats('time').print_stats(50) 336 else: 337 genHeaders() 338