#!/usr/bin/env python # # Copyright (c) 2013-2016 The Khronos Group Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys, time, pdb, string, cProfile from reg import * from generator import write, CGeneratorOptions, COutputGenerator, DocGeneratorOptions, DocOutputGenerator, PyOutputGenerator, ValidityOutputGenerator, HostSynchronizationOutputGenerator, ThreadGeneratorOptions, ThreadOutputGenerator from generator import ParamCheckerGeneratorOptions, ParamCheckerOutputGenerator # debug - start header generation in debugger # dump - dump registry after loading # profile - enable Python profiling # protect - whether to use #ifndef protections # registry - use specified XML registry instead of gl.xml # target - string name of target header, or all targets if None # timeit - time length of registry loading & header generation # validate - validate return & parameter group tags against debug = False dump = False profile = False protect = True target = None timeit = False validate= False # Default input / log files errFilename = None diagFilename = 'diag.txt' regFilename = 'vk.xml' outDir = '.' if __name__ == '__main__': i = 1 while (i < len(sys.argv)): arg = sys.argv[i] i = i + 1 if (arg == '-debug'): write('Enabling debug (-debug)', file=sys.stderr) debug = True elif (arg == '-dump'): write('Enabling dump (-dump)', file=sys.stderr) dump = True elif (arg == '-noprotect'): write('Disabling inclusion protection in output headers', file=sys.stderr) protect = False elif (arg == '-profile'): write('Enabling profiling (-profile)', file=sys.stderr) profile = True elif (arg == '-registry'): regFilename = sys.argv[i] i = i+1 write('Using registry ', regFilename, file=sys.stderr) elif (arg == '-time'): write('Enabling timing (-time)', file=sys.stderr) timeit = True elif (arg == '-validate'): write('Enabling group validation (-validate)', file=sys.stderr) validate = True elif (arg == '-outdir'): outDir = sys.argv[i] i = i+1 write('Using output directory ', outDir, file=sys.stderr) elif (arg[0:1] == '-'): write('Unrecognized argument:', arg, file=sys.stderr) exit(1) else: target = arg write('Using target', target, file=sys.stderr) # Simple timer functions startTime = None def startTimer(): global startTime startTime = time.clock() def endTimer(msg): global startTime endTime = time.clock() if (timeit): write(msg, endTime - startTime) startTime = None # Load & parse registry reg = Registry() startTimer() tree = etree.parse(regFilename) endTimer('Time to make ElementTree =') startTimer() reg.loadElementTree(tree) endTimer('Time to parse ElementTree =') if (validate): reg.validateGroups() if (dump): write('***************************************') write('Performing Registry dump to regdump.txt') write('***************************************') reg.dumpReg(filehandle = open('regdump.txt','w')) # Turn a list of strings into a regexp string matching exactly those strings def makeREstring(list): return '^(' + '|'.join(list) + ')$' # Descriptive names for various regexp patterns used to select # versions and extensions allVersions = allExtensions = '.*' noVersions = noExtensions = None # Copyright text prefixing all headers (list of strings). prefixStrings = [ '/*', '** Copyright (c) 2015-2016 The Khronos Group Inc.', '**', '** Licensed under the Apache License, Version 2.0 (the "License");', '** you may not use this file except in compliance with the License.', '** You may obtain a copy of the License at', '**', '** http://www.apache.org/licenses/LICENSE-2.0', '**', '** Unless required by applicable law or agreed to in writing, software', '** distributed under the License is distributed on an "AS IS" BASIS,', '** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.', '** See the License for the specific language governing permissions and', '** limitations under the License.', '*/', '' ] # Text specific to Vulkan headers vkPrefixStrings = [ '/*', '** This header is generated from the Khronos Vulkan XML API Registry.', '**', '*/', '' ] # Defaults for generating re-inclusion protection wrappers (or not) protectFile = protect protectFeature = protect protectProto = protect buildList = [ # Vulkan 1.0 - header for core API + extensions. # To generate just the core API, # change to 'defaultExtensions = None' below. [ COutputGenerator, CGeneratorOptions( filename = 'include/vulkan/vulkan.h', apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = 'vulkan', addExtensions = None, removeExtensions = None, prefixText = prefixStrings + vkPrefixStrings, genFuncPointers = True, protectFile = protectFile, protectFeature = False, protectProto = '#ifndef', protectProtoStr = 'VK_NO_PROTOTYPES', apicall = 'VKAPI_ATTR ', apientry = 'VKAPI_CALL ', apientryp = 'VKAPI_PTR *', alignFuncParam = 48) ], # Vulkan 1.0 draft - API include files for spec and ref pages # Overwrites include subdirectories in spec source tree # The generated include files do not include the calling convention # macros (apientry etc.), unlike the header files. # Because the 1.0 core branch includes ref pages for extensions, # all the extension interfaces need to be generated, even though # none are used by the core spec itself. [ DocOutputGenerator, DocGeneratorOptions( filename = 'vulkan-docs', apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = None, addExtensions = makeREstring([ 'VK_KHR_sampler_mirror_clamp_to_edge', ]), removeExtensions = makeREstring([ ]), prefixText = prefixStrings + vkPrefixStrings, apicall = '', apientry = '', apientryp = '*', genDirectory = '../../doc/specs/vulkan', alignFuncParam = 48, expandEnumerants = False) ], # Vulkan 1.0 draft - API names to validate man/api spec includes & links [ PyOutputGenerator, DocGeneratorOptions( filename = '../../doc/specs/vulkan/vkapi.py', apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = None, addExtensions = makeREstring([ 'VK_KHR_sampler_mirror_clamp_to_edge', ]), removeExtensions = makeREstring([ ])) ], # Vulkan 1.0 draft - core API validity files for spec # Overwrites validity subdirectories in spec source tree [ ValidityOutputGenerator, DocGeneratorOptions( filename = 'validity', apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = None, addExtensions = makeREstring([ 'VK_KHR_sampler_mirror_clamp_to_edge', ]), removeExtensions = makeREstring([ ]), genDirectory = '../../doc/specs/vulkan') ], # Vulkan 1.0 draft - core API host sync table files for spec # Overwrites subdirectory in spec source tree [ HostSynchronizationOutputGenerator, DocGeneratorOptions( filename = 'hostsynctable', apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = None, addExtensions = makeREstring([ 'VK_KHR_sampler_mirror_clamp_to_edge', ]), removeExtensions = makeREstring([ ]), genDirectory = '../../doc/specs/vulkan') ], # Vulkan 1.0 draft - thread checking layer [ ThreadOutputGenerator, ThreadGeneratorOptions( filename = 'thread_check.h', apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = 'vulkan', addExtensions = None, removeExtensions = None, prefixText = prefixStrings + vkPrefixStrings, genFuncPointers = True, protectFile = protectFile, protectFeature = False, protectProto = True, protectProtoStr = 'VK_PROTOTYPES', apicall = 'VKAPI_ATTR ', apientry = 'VKAPI_CALL ', apientryp = 'VKAPI_PTR *', alignFuncParam = 48, genDirectory = outDir) ], [ ParamCheckerOutputGenerator, ParamCheckerGeneratorOptions( filename = 'parameter_validation.h', apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = 'vulkan', addExtensions = None, removeExtensions = None, prefixText = prefixStrings + vkPrefixStrings, genFuncPointers = True, protectFile = protectFile, protectFeature = False, protectProto = None, protectProtoStr = 'VK_NO_PROTOTYPES', apicall = 'VKAPI_ATTR ', apientry = 'VKAPI_CALL ', apientryp = 'VKAPI_PTR *', alignFuncParam = 48, genDirectory = outDir) ], None ] # create error/warning & diagnostic files if (errFilename): errWarn = open(errFilename,'w') else: errWarn = sys.stderr diag = open(diagFilename, 'w') # check that output directory exists if (not os.path.isdir(outDir)): write('Output directory does not exist: ', outDir) raise def genHeaders(): # Loop over targets, building each generated = 0 for item in buildList: if (item == None): break createGenerator = item[0] genOpts = item[1] if (target and target != genOpts.filename): # write('*** Skipping', genOpts.filename) continue write('*** Building', genOpts.filename) generated = generated + 1 startTimer() gen = createGenerator(errFile=errWarn, warnFile=errWarn, diagFile=diag) reg.setGenerator(gen) reg.apiGen(genOpts) write('** Generated', genOpts.filename) endTimer('Time to generate ' + genOpts.filename + ' =') if (target and generated == 0): write('Failed to generate target:', target) if (debug): pdb.run('genHeaders()') elif (profile): import cProfile, pstats cProfile.run('genHeaders()', 'profile.txt') p = pstats.Stats('profile.txt') p.strip_dirs().sort_stats('time').print_stats(50) else: genHeaders()