1e5c31af7Sopenharmony_ci#!/usr/bin/env python3 2e5c31af7Sopenharmony_ci# 3e5c31af7Sopenharmony_ci# Copyright 2020-2024 The Khronos Group Inc. 4e5c31af7Sopenharmony_ci# 5e5c31af7Sopenharmony_ci# SPDX-License-Identifier: Apache-2.0 6e5c31af7Sopenharmony_ci 7e5c31af7Sopenharmony_ci# Build a spec with requested extension sets and options. 8e5c31af7Sopenharmony_ci# 9e5c31af7Sopenharmony_ci# Usage: makeSpec script-options make-options 10e5c31af7Sopenharmony_ci# Script options are parsed by this script before invoking 'make': 11e5c31af7Sopenharmony_ci# -genpath path - directory for generated files and outputs 12e5c31af7Sopenharmony_ci# -spec core - make a spec with no extensions (default) 13e5c31af7Sopenharmony_ci# -spec khr - make a spec with all KHR extensions 14e5c31af7Sopenharmony_ci# -spec ratified - make a spec with all ratified (KHR + some EXT) extensions 15e5c31af7Sopenharmony_ci# -spec all - make a spec with all registered extensions 16e5c31af7Sopenharmony_ci# -version {1.0 | 1.1 | 1.2 | 1.3 | sc1.0} - make a spec with this core version 17e5c31af7Sopenharmony_ci# -ext name - add specified extension and its dependencies 18e5c31af7Sopenharmony_ci# -clean - clean generated files before building 19e5c31af7Sopenharmony_ci# -registry path - API XML to use instead of default 20e5c31af7Sopenharmony_ci# -apiname name - API name to use instead of default 21e5c31af7Sopenharmony_ci# -test - Build the test spec instead 22e5c31af7Sopenharmony_ci# -v - verbose, print actions before executing them 23e5c31af7Sopenharmony_ci# -n - dry-run, print actions instead of executing them 24e5c31af7Sopenharmony_ci# make-options - all other options are passed to 'make', including 25e5c31af7Sopenharmony_ci# requested build targets 26e5c31af7Sopenharmony_ci 27e5c31af7Sopenharmony_ciimport argparse, copy, io, os, re, string, subprocess, sys 28e5c31af7Sopenharmony_ci 29e5c31af7Sopenharmony_cidef execute(args, results): 30e5c31af7Sopenharmony_ci if results.verbose or results.dryrun: 31e5c31af7Sopenharmony_ci print("'" + "' '".join(args) + "'") 32e5c31af7Sopenharmony_ci if not results.dryrun: 33e5c31af7Sopenharmony_ci subprocess.check_call(args) 34e5c31af7Sopenharmony_ci 35e5c31af7Sopenharmony_ciif __name__ == '__main__': 36e5c31af7Sopenharmony_ci parser = argparse.ArgumentParser() 37e5c31af7Sopenharmony_ci 38e5c31af7Sopenharmony_ci parser.add_argument('-clean', action='store_true', 39e5c31af7Sopenharmony_ci help='Clean generated files before building') 40e5c31af7Sopenharmony_ci parser.add_argument('-extension', action='append', 41e5c31af7Sopenharmony_ci default=[], 42e5c31af7Sopenharmony_ci help='Specify a required extension or extensions to add to targets') 43e5c31af7Sopenharmony_ci parser.add_argument('-genpath', action='store', 44e5c31af7Sopenharmony_ci default='gen', 45e5c31af7Sopenharmony_ci help='Path to directory containing generated files') 46e5c31af7Sopenharmony_ci parser.add_argument('-spec', action='store', 47e5c31af7Sopenharmony_ci choices=[ 'core', 'khr', 'ratified', 'all' ], 48e5c31af7Sopenharmony_ci default='core', 49e5c31af7Sopenharmony_ci help='Type of spec to generate') 50e5c31af7Sopenharmony_ci parser.add_argument('-version', action='store', 51e5c31af7Sopenharmony_ci choices=[ '1.0', '1.1', '1.2', '1.3', 'sc1.0' ], 52e5c31af7Sopenharmony_ci default='1.3', 53e5c31af7Sopenharmony_ci help='Type of spec to generate') 54e5c31af7Sopenharmony_ci parser.add_argument('-registry', action='store', 55e5c31af7Sopenharmony_ci default=None, 56e5c31af7Sopenharmony_ci help='Path to API XML registry file specifying version and extension dependencies') 57e5c31af7Sopenharmony_ci parser.add_argument('-apiname', action='store', 58e5c31af7Sopenharmony_ci default=None, 59e5c31af7Sopenharmony_ci help='API name to generate') 60e5c31af7Sopenharmony_ci parser.add_argument('-test', action='store_true', 61e5c31af7Sopenharmony_ci help='Build the test spec instead of the Vulkan spec') 62e5c31af7Sopenharmony_ci parser.add_argument('-n', action='store_true', dest='dryrun', 63e5c31af7Sopenharmony_ci help='Only prints actions, do not execute them') 64e5c31af7Sopenharmony_ci parser.add_argument('-v', action='store_true', dest='verbose', 65e5c31af7Sopenharmony_ci help='Print actions before executing them') 66e5c31af7Sopenharmony_ci 67e5c31af7Sopenharmony_ci (results, options) = parser.parse_known_args() 68e5c31af7Sopenharmony_ci 69e5c31af7Sopenharmony_ci # Ensure genpath is an absolute path, not relative 70e5c31af7Sopenharmony_ci if results.genpath[0] != '/': 71e5c31af7Sopenharmony_ci results.genpath = os.getcwd() + '/' + results.genpath 72e5c31af7Sopenharmony_ci 73e5c31af7Sopenharmony_ci # Look for scripts/extdependency.py 74e5c31af7Sopenharmony_ci # This requires makeSpec to be invoked from the repository root, but we 75e5c31af7Sopenharmony_ci # could derive that path. 76e5c31af7Sopenharmony_ci sys.path.insert(0, 'scripts') 77e5c31af7Sopenharmony_ci from extdependency import ApiDependencies 78e5c31af7Sopenharmony_ci deps = ApiDependencies(results.registry, results.apiname) 79e5c31af7Sopenharmony_ci 80e5c31af7Sopenharmony_ci # List of versions to build with from the requested -version 81e5c31af7Sopenharmony_ci # This should come from the extdependency module as well, eventually 82e5c31af7Sopenharmony_ci #@ Note that at present, building sc1.0 does *not* include Vulkan 1.3 automatically. 83e5c31af7Sopenharmony_ci versionDict = { 84e5c31af7Sopenharmony_ci '1.0' : [ 'VK_VERSION_1_0' ], 85e5c31af7Sopenharmony_ci '1.1' : [ 'VK_VERSION_1_0', 'VK_VERSION_1_1' ], 86e5c31af7Sopenharmony_ci '1.2' : [ 'VK_VERSION_1_0', 'VK_VERSION_1_1', 'VK_VERSION_1_2' ], 87e5c31af7Sopenharmony_ci '1.3' : [ 'VK_VERSION_1_0', 'VK_VERSION_1_1', 'VK_VERSION_1_2', 'VK_VERSION_1_3' ], 88e5c31af7Sopenharmony_ci 'sc1.0' : [ 'VK_VERSION_1_0', 'VK_VERSION_1_1', 'VK_VERSION_1_2', 'VKSC_VERSION_1_0' ], 89e5c31af7Sopenharmony_ci } 90e5c31af7Sopenharmony_ci versions = 'VERSIONS={}'.format(' '.join(versionDict[results.version])) 91e5c31af7Sopenharmony_ci 92e5c31af7Sopenharmony_ci # List of extensions to build with from the requested -spec 93e5c31af7Sopenharmony_ci # Also construct a spec title 94e5c31af7Sopenharmony_ci # This should respect version dependencies as well 95e5c31af7Sopenharmony_ci if results.spec == 'core': 96e5c31af7Sopenharmony_ci title = '' 97e5c31af7Sopenharmony_ci exts = set() 98e5c31af7Sopenharmony_ci elif results.spec == 'khr': 99e5c31af7Sopenharmony_ci title = 'with all KHR extensions' 100e5c31af7Sopenharmony_ci exts = set(deps.khrExtensions()) 101e5c31af7Sopenharmony_ci elif results.spec == 'ratified': 102e5c31af7Sopenharmony_ci title = 'with all ratified extensions' 103e5c31af7Sopenharmony_ci exts = set(deps.ratifiedExtensions()) 104e5c31af7Sopenharmony_ci elif results.spec == 'all': 105e5c31af7Sopenharmony_ci title = 'with all registered extensions' 106e5c31af7Sopenharmony_ci exts = set(deps.allExtensions()) 107e5c31af7Sopenharmony_ci 108e5c31af7Sopenharmony_ci # List of explicitly requested extension and all its supported dependencies 109e5c31af7Sopenharmony_ci extraexts = set() 110e5c31af7Sopenharmony_ci for name in results.extension: 111e5c31af7Sopenharmony_ci if name in deps.allExtensions(): 112e5c31af7Sopenharmony_ci extraexts.add(name) 113e5c31af7Sopenharmony_ci for dep in deps.children(name): 114e5c31af7Sopenharmony_ci if dep in deps.allExtensions(): 115e5c31af7Sopenharmony_ci extraexts.update({dep}) 116e5c31af7Sopenharmony_ci else: 117e5c31af7Sopenharmony_ci raise Exception(f'ERROR: unknown extension {name}') 118e5c31af7Sopenharmony_ci 119e5c31af7Sopenharmony_ci # See if any explicitly requested extensions are not implicitly requested 120e5c31af7Sopenharmony_ci # Add any such extensions to the spec title 121e5c31af7Sopenharmony_ci extraexts -= exts 122e5c31af7Sopenharmony_ci if len(extraexts) > 0: 123e5c31af7Sopenharmony_ci exts.update(extraexts) 124e5c31af7Sopenharmony_ci if title != '': 125e5c31af7Sopenharmony_ci title += ' and ' + ', '.join(sorted(extraexts)) 126e5c31af7Sopenharmony_ci else: 127e5c31af7Sopenharmony_ci title += 'with ' + ', '.join(sorted(extraexts)) 128e5c31af7Sopenharmony_ci 129e5c31af7Sopenharmony_ci if title != '': 130e5c31af7Sopenharmony_ci title = '(' + title + ')' 131e5c31af7Sopenharmony_ci 132e5c31af7Sopenharmony_ci # Finally, actually invoke make as needed for the targets 133e5c31af7Sopenharmony_ci args = [ 'make', 'GENERATED=' + results.genpath ] 134e5c31af7Sopenharmony_ci 135e5c31af7Sopenharmony_ci if results.clean: 136e5c31af7Sopenharmony_ci # If OUTDIR is set on the command line, pass it to the 'clean' 137e5c31af7Sopenharmony_ci # target so it is cleaned as well. 138e5c31af7Sopenharmony_ci cleanopts = ['clean'] 139e5c31af7Sopenharmony_ci for opt in options: 140e5c31af7Sopenharmony_ci if opt[:7] == 'OUTDIR=': 141e5c31af7Sopenharmony_ci cleanopts.append(opt) 142e5c31af7Sopenharmony_ci try: 143e5c31af7Sopenharmony_ci execute(args + cleanopts, results) 144e5c31af7Sopenharmony_ci except: 145e5c31af7Sopenharmony_ci sys.exit(1) 146e5c31af7Sopenharmony_ci 147e5c31af7Sopenharmony_ci # Use the test spec if specified. This is used solely by self tests. 148e5c31af7Sopenharmony_ci rootdir = os.path.dirname(os.path.abspath(__file__)) 149e5c31af7Sopenharmony_ci if results.test: 150e5c31af7Sopenharmony_ci # Set the spec source to the test spec 151e5c31af7Sopenharmony_ci args.append(f'SPECSRC={rootdir}/build_tests/testspec.adoc') 152e5c31af7Sopenharmony_ci args.append(f'SPECDIR={rootdir}/build_tests/') 153e5c31af7Sopenharmony_ci # Make sure the build is invariant 154e5c31af7Sopenharmony_ci args.append('SPECREVISION=1.2.3') 155e5c31af7Sopenharmony_ci args.append('SPECDATE=\\"2100-11-22 00:33:44Z\\"') 156e5c31af7Sopenharmony_ci args.append('SPECREMARK=\\"test build\\"') 157e5c31af7Sopenharmony_ci 158e5c31af7Sopenharmony_ci args.append(versions) 159e5c31af7Sopenharmony_ci 160e5c31af7Sopenharmony_ci # The actual target 161e5c31af7Sopenharmony_ci if len(exts) > 0: 162e5c31af7Sopenharmony_ci args.append(f'EXTENSIONS={" ".join(sorted(exts))}') 163e5c31af7Sopenharmony_ci args.append(f'APITITLE={title}') 164e5c31af7Sopenharmony_ci args += options 165e5c31af7Sopenharmony_ci 166e5c31af7Sopenharmony_ci try: 167e5c31af7Sopenharmony_ci execute(args, results) 168e5c31af7Sopenharmony_ci except: 169e5c31af7Sopenharmony_ci sys.exit(1) 170