From: Mike Schuchardt Date: Mon, 22 Jul 2019 23:57:15 +0000 (-0700) Subject: scripts: Port codegen script from VVL X-Git-Tag: upstream/1.2.179~237 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6a0ba2cdd9467c33a8accf7146962f8bbdd73e44;p=platform%2Fupstream%2FVulkan-Tools.git scripts: Port codegen script from VVL --- diff --git a/CMakeLists.txt b/CMakeLists.txt index e6ba640..4c921b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,6 +137,16 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang") endif() endif() +# Optional codegen target +if(PYTHONINTERP_FOUND) + add_custom_target(VulkanTools_generated_source + COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/scripts/generate_source.py + ${VulkanRegistry_DIR} --incremental + ) +else() + message("WARNING: VulkanTools_generated_source target requires python 3") +endif() + if(APPLE) include(mac_common.cmake) endif() diff --git a/scripts/common_codegen.py b/scripts/common_codegen.py index 8954532..d56ebac 100644 --- a/scripts/common_codegen.py +++ b/scripts/common_codegen.py @@ -18,10 +18,7 @@ # # Author: Mark Lobodzinski -import os,re,sys,string -import xml.etree.ElementTree as etree -from generator import * -from collections import namedtuple +import os # Copyright text prefixing all headers (list of strings). prefixStrings = [ @@ -71,3 +68,7 @@ def GetFeatureProtect(interface): if platform is not None: protect = platform_dict[platform] return protect + +# helper to define paths relative to the repo root +def repo_relative(path): + return os.path.abspath(os.path.join(os.path.dirname(__file__), '..', path)) diff --git a/scripts/generate_source.py b/scripts/generate_source.py new file mode 100755 index 0000000..c4be24f --- /dev/null +++ b/scripts/generate_source.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 +# Copyright (c) 2019 The Khronos Group Inc. +# Copyright (c) 2019 Valve Corporation +# Copyright (c) 2019 LunarG, Inc. +# Copyright (c) 2019 Google 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. +# +# Author: Mike Schuchardt + +import argparse +import filecmp +import os +import shutil +import subprocess +import sys +import tempfile + +import common_codegen + +# files to exclude from --verify check +verify_exclude = ['.clang-format'] + +def main(argv): + parser = argparse.ArgumentParser(description='Generate source code for this repository') + parser.add_argument('registry', metavar='REGISTRY_PATH', help='path to the Vulkan-Headers registry directory') + group = parser.add_mutually_exclusive_group() + group.add_argument('-i', '--incremental', action='store_true', help='only update repo files that change') + group.add_argument('-v', '--verify', action='store_true', help='verify repo files match generator output') + args = parser.parse_args(argv) + + gen_cmds = [[common_codegen.repo_relative('scripts/kvt_genvk.py'), + '-registry', os.path.abspath(os.path.join(args.registry, 'vk.xml')), + '-quiet', + filename] for filename in ['vk_typemap_helper.h', + 'mock_icd.h', + 'mock_icd.cpp']] + + repo_dir = common_codegen.repo_relative('icd/generated') + + # get directory where generators will run + if args.verify or args.incremental: + # generate in temp directory so we can compare or copy later + temp_obj = tempfile.TemporaryDirectory(prefix='VulkanLoader_generated_source_') + temp_dir = temp_obj.name + gen_dir = temp_dir + else: + # generate directly in the repo + gen_dir = repo_dir + + # run each code generator + for cmd in gen_cmds: + print(' '.join(cmd)) + try: + subprocess.check_call([sys.executable] + cmd, cwd=gen_dir) + except Exception as e: + print('ERROR:', str(e)) + return 1 + + # optional post-generation steps + if args.verify: + # compare contents of temp dir and repo + temp_files = set(os.listdir(temp_dir)) + repo_files = set(os.listdir(repo_dir)) + files_match = True + for filename in sorted((temp_files | repo_files) - set(verify_exclude)): + if filename not in repo_files: + print('ERROR: Missing repo file', filename) + files_match = False + elif filename not in temp_files: + print('ERROR: Missing generator for', filename) + files_match = False + elif not filecmp.cmp(os.path.join(temp_dir, filename), + os.path.join(repo_dir, filename), + shallow=False): + print('ERROR: Repo files do not match generator output for', filename) + files_match = False + + # return code for test scripts + if files_match: + print('SUCCESS: Repo files match generator output') + return 0 + return 1 + + elif args.incremental: + # copy missing or differing files from temp directory to repo + for filename in os.listdir(temp_dir): + temp_filename = os.path.join(temp_dir, filename) + repo_filename = os.path.join(repo_dir, filename) + if not os.path.exists(repo_filename) or \ + not filecmp.cmp(temp_filename, repo_filename, shallow=False): + print('update', repo_filename) + shutil.copyfile(temp_filename, repo_filename) + + return 0 + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) + diff --git a/scripts/kvt_genvk.py b/scripts/kvt_genvk.py index 598f000..1d2f255 100644 --- a/scripts/kvt_genvk.py +++ b/scripts/kvt_genvk.py @@ -26,7 +26,6 @@ def startTimer(timeit): def endTimer(timeit, msg): global startTime - endTime = time.clock() if timeit: endTime = time.process_time() write(msg, endTime - startTime, file=sys.stderr) @@ -34,7 +33,7 @@ def endTimer(timeit, msg): # Turn a list of strings into a regexp string matching exactly those strings def makeREstring(list, default = None): - if len(list) > 0 or default == None: + if len(list) > 0 or default is None: return '^(' + '|'.join(list) + ')$' else: return default @@ -112,7 +111,7 @@ def makeGenOpts(args): # Defaults for generating re-inclusion protection wrappers (or not) protectFeature = protect - # An API style convention object + # An API style conventions object conventions = VulkanConventions() # Helper file generator options for typemap_helper.h @@ -291,6 +290,10 @@ if __name__ == '__main__': args = parser.parse_args() + # default scripts path to be same as registry + if not args.scripts: + args.scripts = os.path.dirname(args.registry) + scripts_directory_path = os.path.dirname(os.path.abspath(__file__)) registry_headers_path = os.path.join(scripts_directory_path, args.scripts) sys.path.insert(0, registry_headers_path)