2 # Copyright (c) 2019-2023 The Khronos Group Inc.
3 # Copyright (c) 2019-2023 Valve Corporation
4 # Copyright (c) 2019-2023 LunarG, Inc.
5 # Copyright (c) 2019-2023 Google Inc.
6 # Copyright (c) 2023-2023 RasterGrid Kft.
8 # Licensed under the Apache License, Version 2.0 (the "License");
9 # you may not use this file except in compliance with the License.
10 # You may obtain a copy of the License at
12 # http://www.apache.org/licenses/LICENSE-2.0
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS,
16 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 # See the License for the specific language governing permissions and
18 # limitations under the License.
20 # Author: Mike Schuchardt <mikes@lunarg.com>
33 # files to exclude from --verify check
34 verify_exclude
= ['.clang-format']
37 parser
= argparse
.ArgumentParser(description
='Generate source code for this repository')
38 parser
.add_argument('--api',
40 choices
=['vulkan', 'vulkansc'],
41 help='Specify API name to generate')
42 parser
.add_argument('--generated-version', help='sets the header version used to generate the repo')
43 parser
.add_argument('registry', metavar
='REGISTRY_PATH', help='path to the Vulkan-Headers registry directory')
44 group
= parser
.add_mutually_exclusive_group()
45 group
.add_argument('-i', '--incremental', action
='store_true', help='only update repo files that change')
46 group
.add_argument('-v', '--verify', action
='store_true', help='verify repo files match generator output')
47 args
= parser
.parse_args(argv
)
49 # output paths and the list of files in the path
50 files_to_gen
= {str(os
.path
.join('icd','generated')) : ['vk_typemap_helper.h',
51 'function_definitions.h',
52 'function_declarations.h'],
53 str(os
.path
.join('vulkaninfo','generated')): ['vulkaninfo.hpp']}
55 #base directory for the source repository
56 repo_dir
= common_codegen
.repo_relative('')
58 # Update the api_version in the respective json files
59 if args
.generated_version
:
61 json_files
.append(common_codegen
.repo_relative('icd/VkICD_mock_icd.json.in'))
62 for json_file
in json_files
:
63 with
open(json_file
) as f
:
66 data
["ICD"]["api_version"] = args
.generated_version
68 with
open(json_file
, mode
='w', encoding
='utf-8', newline
='\n') as f
:
69 f
.write(json
.dumps(data
, indent
=4))
71 # get directory where generators will run if needed
72 if args
.verify
or args
.incremental
:
73 # generate in temp directory so we can compare or copy later
74 temp_obj
= tempfile
.TemporaryDirectory(prefix
='VulkanLoader_generated_source_')
75 temp_dir
= temp_obj
.name
76 for path
in files_to_gen
.keys():
77 os
.makedirs(os
.path
.join(temp_dir
, path
))
79 registry
= os
.path
.abspath(os
.path
.join(args
.registry
, 'vk.xml'))
80 if not os
.path
.isfile(registry
):
81 registry
= os
.path
.abspath(os
.path
.join(args
.registry
, 'Vulkan-Headers/registry/vk.xml'))
82 if not os
.path
.isfile(registry
):
83 print(f
'cannot find vk.xml in {args.registry}')
86 # run each code generator
87 for path
, filenames
in files_to_gen
.items():
88 for filename
in filenames
:
89 if args
.verify
or args
.incremental
:
90 output_path
= os
.path
.join(temp_dir
, path
)
92 output_path
= common_codegen
.repo_relative(path
)
94 cmd
= [common_codegen
.repo_relative(os
.path
.join('scripts','kvt_genvk.py')),
96 '-registry', registry
,
97 '-quiet', '-directory', output_path
, filename
]
100 if args
.verify
or args
.incremental
:
101 subprocess
.check_call([sys
.executable
] + cmd
, cwd
=temp_dir
)
103 subprocess
.check_call([sys
.executable
] + cmd
, cwd
=repo_dir
)
105 except Exception as e
:
106 print('ERROR:', str(e
))
109 # optional post-generation steps
111 # compare contents of temp dir and repo
113 for path
in files_to_gen
.keys():
114 temp_files
[path
] = set()
115 temp_files
[path
].update(set(os
.listdir(os
.path
.join(temp_dir
, path
))))
118 for path
in files_to_gen
.keys():
119 repo_files
[path
] = set()
120 repo_files
[path
].update(set(os
.listdir(os
.path
.join(repo_dir
, path
))) - set(verify_exclude
))
123 for path
in files_to_gen
.keys():
124 for filename
in sorted((temp_files
[path
] | repo_files
[path
])):
125 if filename
not in repo_files
[path
]:
126 print('ERROR: Missing repo file', filename
)
128 elif filename
not in temp_files
[path
]:
129 print('ERROR: Missing generator for', filename
)
131 elif not filecmp
.cmp(os
.path
.join(temp_dir
, path
, filename
),
132 os
.path
.join(repo_dir
, path
, filename
),
134 print('ERROR: Repo files do not match generator output for', filename
)
137 # return code for test scripts
139 print('SUCCESS: Repo files match generator output')
143 elif args
.incremental
:
144 # copy missing or differing files from temp directory to repo
145 for path
in files_to_gen
.keys():
146 for filename
in os
.listdir(os
.path
.join(temp_dir
,path
)):
147 temp_filename
= os
.path
.join(temp_dir
, path
, filename
)
148 repo_filename
= os
.path
.join(repo_dir
, path
, filename
)
149 if not os
.path
.exists(repo_filename
) or \
150 not filecmp
.cmp(temp_filename
, repo_filename
, shallow
=False):
151 print('update', repo_filename
)
152 shutil
.copyfile(temp_filename
, repo_filename
)
156 if __name__
== '__main__':
157 sys
.exit(main(sys
.argv
[1:]))