1#!/usr/bin/env python3 2# Copyright (c) 2019 The Khronos Group Inc. 3# Copyright (c) 2019 Valve Corporation 4# Copyright (c) 2019 LunarG, Inc. 5# Copyright (c) 2019 Google Inc. 6# 7# Licensed under the Apache License, Version 2.0 (the "License"); 8# you may not use this file except in compliance with the License. 9# You may obtain a copy of the License at 10# 11# http://www.apache.org/licenses/LICENSE-2.0 12# 13# Unless required by applicable law or agreed to in writing, software 14# distributed under the License is distributed on an "AS IS" BASIS, 15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16# See the License for the specific language governing permissions and 17# limitations under the License. 18# 19# Author: Mike Schuchardt <mikes@lunarg.com> 20 21import argparse 22import common_codegen 23import filecmp 24import os 25import shutil 26import subprocess 27import sys 28import tempfile 29 30# files to exclude from --verify check 31verify_exclude = ['.clang-format'] 32 33def main(argv): 34 parser = argparse.ArgumentParser(description='Generate source code for this repository') 35 parser.add_argument('registry', metavar='REGISTRY_PATH', help='path to the Vulkan-Headers registry directory') 36 group = parser.add_mutually_exclusive_group() 37 group.add_argument('-i', '--incremental', action='store_true', help='only update repo files that change') 38 group.add_argument('-v', '--verify', action='store_true', help='verify repo files match generator output') 39 args = parser.parse_args(argv) 40 41 gen_cmds = [[common_codegen.repo_relative('scripts/loader_genvk.py'), 42 '-registry', os.path.abspath(os.path.join(args.registry, 'vk.xml')), 43 '-quiet', 44 filename] for filename in ['vk_dispatch_table_helper.h', 45 'vk_layer_dispatch_table.h', 46 'vk_loader_extensions.h', 47 'vk_loader_extensions.c', 48 'vk_object_types.h', 49 'loader_generated_header_version.cmake']] 50 51 repo_dir = common_codegen.repo_relative('loader/generated') 52 53 # get directory where generators will run 54 if args.verify or args.incremental: 55 # generate in temp directory so we can compare or copy later 56 temp_obj = tempfile.TemporaryDirectory(prefix='VulkanLoader_generated_source_') 57 temp_dir = temp_obj.name 58 gen_dir = temp_dir 59 else: 60 # generate directly in the repo 61 gen_dir = repo_dir 62 63 # run each code generator 64 for cmd in gen_cmds: 65 print(' '.join(cmd)) 66 try: 67 subprocess.check_call([sys.executable] + cmd, 68 # ignore generator output, vk_validation_stats.py is especially noisy 69 stdout=subprocess.DEVNULL, 70 cwd=gen_dir) 71 except Exception as e: 72 print('ERROR:', str(e)) 73 return 1 74 75 # optional post-generation steps 76 if args.verify: 77 # compare contents of temp dir and repo 78 temp_files = set(os.listdir(temp_dir)) 79 repo_files = set(os.listdir(repo_dir)) 80 files_match = True 81 for filename in sorted((temp_files | repo_files) - set(verify_exclude)): 82 if filename not in repo_files: 83 print('ERROR: Missing repo file', filename) 84 files_match = False 85 elif filename not in temp_files: 86 print('ERROR: Missing generator for', filename) 87 files_match = False 88 elif not filecmp.cmp(os.path.join(temp_dir, filename), 89 os.path.join(repo_dir, filename), 90 shallow=False): 91 print('ERROR: Repo files do not match generator output for', filename) 92 files_match = False 93 94 # return code for test scripts 95 if files_match: 96 print('SUCCESS: Repo files match generator output') 97 return 0 98 return 1 99 100 elif args.incremental: 101 # copy missing or differing files from temp directory to repo 102 for filename in os.listdir(temp_dir): 103 temp_filename = os.path.join(temp_dir, filename) 104 repo_filename = os.path.join(repo_dir, filename) 105 if not os.path.exists(repo_filename) or \ 106 not filecmp.cmp(temp_filename, repo_filename, shallow=False): 107 print('update', repo_filename) 108 shutil.copyfile(temp_filename, repo_filename) 109 110 return 0 111 112if __name__ == '__main__': 113 sys.exit(main(sys.argv[1:])) 114 115