1#!/usr/bin/env python3 2# 3# Copyright 2020-2021 The Khronos Group Inc. 4# 5# SPDX-License-Identifier: Apache-2.0 6 7# Build a spec with requested extension sets and options. 8# 9# Usage: makeSpec script-options make-options 10# Script options are parsed by this script before invoking 'make': 11# -genpath path - directory for generated files and outputs 12# -spec core - make a spec with no extensions (default) 13# -spec khr - make a spec with all KHR extensions 14# -spec all - make a spec with all registered extensions 15# -version {1.0 | 1.1 | 1.2} - make a spec with this core version 16# -ext name - add specified extension and its dependencies 17# -clean - clean generated files before building 18# -registry path - API XML to use instead of default 19# -apiname name - API name to use instead of default 20# -v - verbose, print actions before executing them 21# -n - dry-run, print actions instead of executing them 22# make-options - all other options are passed to 'make', including 23# requested build targets 24 25import argparse, copy, io, os, re, string, subprocess, sys 26 27def execute(args, results): 28 if results.verbose or results.dryrun: 29 print("'" + "' '".join(args) + "'") 30 if not results.dryrun: 31 subprocess.check_call(args) 32 33if __name__ == '__main__': 34 parser = argparse.ArgumentParser() 35 36 parser.add_argument('-clean', action='store_true', 37 help='Clean generated files before building') 38 parser.add_argument('-extension', action='append', 39 default=[], 40 help='Specify a required extension or extensions to add to targets') 41 parser.add_argument('-genpath', action='store', 42 default='gen', 43 help='Path to directory containing generated files') 44 parser.add_argument('-spec', action='store', 45 choices=[ 'core', 'khr', 'all' ], 46 default='core', 47 help='Type of spec to generate') 48 parser.add_argument('-version', action='store', 49 choices=[ '1.0', '1.1', '1.2' ], 50 default='1.2', 51 help='Type of spec to generate') 52 53 parser.add_argument('-registry', action='store', 54 default=None, 55 help='Path to API XML registry file specifying version and extension dependencies') 56 parser.add_argument('-apiname', action='store', 57 default=None, 58 help='API name to generate') 59 60 parser.add_argument('-n', action='store_true', dest='dryrun', 61 help='Only prints actions, do not execute them') 62 parser.add_argument('-v', action='store_true', dest='verbose', 63 help='Print actions before executing them') 64 65 (results, options) = parser.parse_known_args() 66 67 # Ensure genpath is an absolute path, not relative 68 if results.genpath[0] != '/': 69 results.genpath = os.getcwd() + '/' + results.genpath 70 71 # Look for scripts/extdependency.py 72 # This requires makeSpec to be invoked from the repository root, but we 73 # could derive that path. 74 sys.path.insert(0, 'scripts') 75 from extdependency import ApiDependencies 76 deps = ApiDependencies(results.registry, results.apiname) 77 78 # List of versions to build with from the requested -version 79 # This should come from the extdependency module as well, eventually 80 versionDict = { 81 '1.0' : [ 'VK_VERSION_1_0' ], 82 '1.1' : [ 'VK_VERSION_1_0', 'VK_VERSION_1_1' ], 83 '1.2' : [ 'VK_VERSION_1_0', 'VK_VERSION_1_1', 'VK_VERSION_1_2' ], 84 } 85 versions = 'VERSIONS={}'.format(' '.join(versionDict[results.version])) 86 87 # List of extensions to build with from the requested -spec 88 # Also construct a spec title 89 # This should respect version dependencies as well 90 if results.spec == 'core': 91 title = '' 92 exts = set() 93 if results.spec == 'khr': 94 title = 'with all KHR extensions' 95 exts = set(deps.khrExtensions()) 96 elif results.spec == 'all': 97 title = 'with all registered extensions' 98 exts = set(deps.allExtensions()) 99 100 # List of explicitly requested extension and all its dependencies 101 extraexts = set() 102 for name in results.extension: 103 if name in extensions: 104 extraexts.add(name) 105 extraexts.update(extensions[name]) 106 else: 107 raise Exception(f'ERROR: unknown extension {name}') 108 109 # See if any explicitly requested extensions are not implicitly requested 110 # Add any such extensions to the spec title 111 extraexts -= exts 112 if len(extraexts) > 0: 113 exts.update(extraexts) 114 if title != '': 115 title += ' and ' + ', '.join(sorted(extraexts)) 116 else: 117 title += 'with ' + ', '.join(sorted(extraexts)) 118 119 if title != '': 120 title = '(' + title + ')' 121 122 # Finally, actually invoke make as needed for the targets 123 args = [ 'make', 'GENERATED=' + results.genpath ] 124 125 if results.clean: 126 execute(args + ['clean'], results) 127 128 args.append(versions) 129 130 # The actual target 131 if len(exts) > 0: 132 args.append('EXTENSIONS={}'.format(' '.join(sorted(exts)))) 133 args.append('APITITLE={}'.format(title)) 134 args += options 135 136 try: 137 execute(args, results) 138 except: 139 sys.exit(1) 140