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# -v - verbose, print actions before executing them 19# -n - dry-run, print actions instead of executing them 20# make-options - all other options are passed to 'make', including 21# requested build targets 22 23import argparse, copy, io, os, re, string, subprocess, sys 24 25def execute(args, results): 26 if results.verbose or results.dryrun: 27 print("'" + "' '".join(args) + "'") 28 if not results.dryrun: 29 subprocess.check_call(args) 30 31if __name__ == '__main__': 32 parser = argparse.ArgumentParser() 33 34 parser.add_argument('-clean', action='store_true', 35 help='Clean generated files before building') 36 parser.add_argument('-extension', action='append', 37 default=[], 38 help='Specify a required extension or extensions to add to targets') 39 parser.add_argument('-genpath', action='store', 40 default='gen', 41 help='Path to directory containing generated files') 42 parser.add_argument('-spec', action='store', 43 choices=[ 'core', 'khr', 'all' ], 44 default='core', 45 help='Type of spec to generate') 46 parser.add_argument('-version', action='store', 47 choices=[ '1.0', '1.1', '1.2' ], 48 default='1.2', 49 help='Type of spec to generate') 50 parser.add_argument('-n', action='store_true', dest='dryrun', 51 help='Only prints actions, do not execute them') 52 parser.add_argument('-v', action='store_true', dest='verbose', 53 help='Print actions before executing them') 54 55 (results, options) = parser.parse_known_args() 56 57 # Ensure genpath is an absolute path, not relative 58 if results.genpath[0] != '/': 59 results.genpath = os.getcwd() + '/' + results.genpath 60 61 # Ensure extDependency.py exists and is up to date before importing it 62 try: 63 execute(['make', 'GENERATED=' + results.genpath, 'extDependency'], results) 64 65 # Look for extDependency.py in the specified directory and import it 66 sys.path.insert(0, results.genpath) 67 from extDependency import extensions, allExts, khrExts 68 except: 69 print('Cannot execute "make extDependency" or determine correct extension list', file=sys.stderr) 70 71 # List of versions to build with from the requested -version 72 versionDict = { 73 '1.0' : [ 'VK_VERSION_1_0' ], 74 '1.1' : [ 'VK_VERSION_1_0', 'VK_VERSION_1_1' ], 75 '1.2' : [ 'VK_VERSION_1_0', 'VK_VERSION_1_1', 'VK_VERSION_1_2' ], 76 } 77 versions = 'VERSIONS={}'.format(' '.join(versionDict[results.version])) 78 79 # List of extensions to build with from the requested -spec 80 # Also construct a spec title 81 if results.spec == 'core': 82 title = '' 83 exts = set() 84 if results.spec == 'khr': 85 title = 'with all KHR extensions' 86 exts = set(khrExts) 87 elif results.spec == 'all': 88 title = 'with all registered extensions' 89 exts = set(allExts) 90 91 # List of explicitly requested extension and all its dependencies 92 extraexts = set() 93 for name in results.extension: 94 if name in extensions: 95 extraexts.add(name) 96 extraexts.update(extensions[name]) 97 else: 98 print('ERROR: unknown extension', name, file=sys.stderr) 99 sys.exit(1) 100 101 # See if any explicitly requested extensions aren't implicitly requested 102 # Add any such extensions to the spec title 103 extraexts -= exts 104 if len(extraexts) > 0: 105 exts.update(extraexts) 106 if title != '': 107 title += ' and ' + ', '.join(sorted(extraexts)) 108 else: 109 title += 'with ' + ', '.join(sorted(extraexts)) 110 111 if title != '': 112 title = '(' + title + ')' 113 114 # Finally, actually invoke make as needed for the targets 115 args = [ 'make', 'GENERATED=' + results.genpath ] 116 117 if results.clean: 118 execute(args + ['clean'], results) 119 120 args.append(versions) 121 122 # The actual target 123 if len(exts) > 0: 124 args.append('EXTENSIONS={}'.format(' '.join(sorted(exts)))) 125 args.append('APITITLE={}'.format(title)) 126 args += options 127 128 try: 129 execute(args, results) 130 except: 131 sys.exit(1) 132