• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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