yum-mirror/VkFFT
git clone https://git.yummers.dev/yum-mirror/VkFFT
ba7001c
master
1#!/usr/bin/python 2 3#-------------------------------------------------------------------------------------------------------------------------------------------------------------- 4# 5# SingleHeader/MakeSingleHeader.py 6# 7# Copyright 2020-2021 Apple Inc. 8# 9# Licensed under the Apache License, Version 2.0 (the "License"); 10# you may not use this file except in compliance with the License. 11# You may obtain a copy of the License at 12# 13# http://www.apache.org/licenses/LICENSE-2.0 14# 15# Unless required by applicable law or agreed to in writing, software 16# distributed under the License is distributed on an "AS IS" BASIS, 17# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18# See the License for the specific language governing permissions and 19# limitations under the License. 20# 21#-------------------------------------------------------------------------------------------------------------------------------------------------------------- 22 23import argparse 24import datetime 25import logging 26import os 27import re 28import subprocess 29import sys 30 31#-------------------------------------------------------------------------------------------------------------------------------------------------------------- 32 33class HeaderPrefix (object ): 34__template = ('//\n' 35'// {file}\n' 36'//\n' 37'// {meta_data}\n' 38'//\n' 39'// Copyright 2020-2021 Apple Inc.\n' 40'//\n' 41'// Licensed under the Apache License, Version 2.0 (the "License");\n' 42'// you may not use this file except in compliance with the License.\n' 43'// You may obtain a copy of the License at\n' 44'//\n' 45'// http://www.apache.org/licenses/LICENSE-2.0\n' 46'//\n' 47'// Unless required by applicable law or agreed to in writing, software\n' 48'// distributed under the License is distributed on an "AS IS" BASIS,\n' 49'// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n' 50'// See the License for the specific language governing permissions and\n' 51'// limitations under the License.\n' 52'//\n' 53'\n' ) 54 55__template_commit = 'Autogenerated from commit {commit}.' 56__template_date = 'Autogenerated on %B %d, %Y.' 57 58def __init__ (self ,file ): 59self .__file = file 60 61def __str__ (self ): 62return self .__template .format (file = self .__file ,meta_data = self .__meta_data_string () ) 63 64def __get_commit_hash (self ): 65git_commit_hash = None 66 67try : 68git_dir = os .path .dirname (os .path .realpath (__file__ ) ) 69proc = subprocess .Popen ( ['git' ,'rev-parse' ,'HEAD' ],cwd = git_dir ,stdout = subprocess .PIPE ,stderr = subprocess .PIPE ) 70git_commit_hash = proc .stdout .read ().decode ('utf-8' ,'replace' ).strip () 71except : 72logging .error ('Failed to determine git commit hash!' ) 73pass 74 75return git_commit_hash 76 77def __get_commit_string (self ): 78meta_data = None 79git_commit_hash = self .__get_commit_hash () 80 81if git_commit_hash : 82meta_data = self .__template_commit .format (commit = git_commit_hash ) 83 84return meta_data 85 86def __get_date_string (self ): 87today = datetime .date .today () 88 89return today .strftime (self .__template_date ) 90 91def __meta_data_string (self ): 92meta_data = self .__get_commit_string () 93 94if not meta_data : 95meta_data = self .__get_date_string () 96 97return meta_data 98 99#-------------------------------------------------------------------------------------------------------------------------------------------------------------- 100 101class SingleHeader (object ): 102__pragma_once = '#pragma once\n\n' 103 104def __init__ (self ): 105self .__header_paths = list () 106 107def __str__ (self ): 108return self .process () 109 110def append (self ,header_path ): 111self .__header_paths .append (header_path ) 112 113def process (self ): 114out_header = self .__pragma_once 115 116self .__included_headers = set () 117self .__base_path = list () 118 119for header_path in self .__header_paths : 120out_header += self .__process_header (header_path ) 121 122return self .__strip_empty_lines (out_header ) 123 124def __read_header (self ,path ): 125path = os .path .realpath (path ) 126 127try : 128f = open (path ,'r' ) 129except : 130raise RuntimeError ('Failed to open file \"' + path + '\" for read!' ) 131 132return f .read () 133 134def __strip_pragma_once (self ,header ): 135return re .sub ('\\s*#pragma once\s*\\/\\/-*\\n' ,'' ,header ) 136 137def __strip_comments (self ,header ): 138return re .sub ('^//.*\\n' ,'' ,header ,flags = re .MULTILINE ) 139 140def __strip_empty_lines (self ,header ): 141return re .sub ('\\n\\n+' ,'\\n\\n' ,header ,flags = re .MULTILINE ) 142 143def __substitute_include_directive (self ,match ): 144header_path = match .group ('HEADER_PATH' ) 145 146logging .info ('\tSubstituting \"' + header_path + '\"...' ) 147 148return self .__process_header (os .path .join (self .__base_path [- 1 ],header_path ) ) 149 150def __process_include_directives (self ,header ): 151return re .sub ('^\\s*#include\\s\\"(?P<HEADER_PATH>\\S*)\\"' ,self .__substitute_include_directive ,header ,flags = re .MULTILINE ) 152 153def __process_foundation_directives (self ,header ): 154if header .find ("#include <Foundation/Foundation.hpp>" )!= - 1 : 155logging .info ('\tSubstituting <Foundation/Foundation.hpp>...' ) 156return header .replace ("#include <Foundation/Foundation.hpp>" ,self .__process_header (os .path .join (self .__base_path [- 1 ],"../Foundation/Foundation.hpp" ) ) ) 157return header 158 159 160def __process_header (self ,header_path ): 161out_header = '' 162 163header_path = os .path .realpath (header_path ) 164 165if not header_path in self .__included_headers : 166logging .info ('Processing \"' + header_path + '\"...' ) 167 168self .__base_path .append (os .path .dirname (header_path ) ) 169self .__included_headers .add (header_path ) 170 171out_header = self .__read_header (header_path ) 172out_header = self .__strip_pragma_once (out_header ) 173out_header = self .__strip_comments (out_header ) 174out_header = self .__process_include_directives (out_header ) 175out_header = self .__process_foundation_directives (out_header ) 176 177self .__base_path .pop () 178else : 179logging .info ('\tSkipping \"' + header_path + '\"...' ) 180 181return out_header 182 183#-------------------------------------------------------------------------------------------------------------------------------------------------------------- 184 185def create_argument_parser (): 186parser = argparse .ArgumentParser () 187base_path = os .path .dirname (os .path .realpath (__file__ ) ) 188output_path = os .path .join (base_path ,'Metal.hpp' ) 189 190parser .add_argument ('-o' ,'--output' ,dest = 'output_path' ,metavar = 'PATH' ,default = output_path ,help = 'Output path for the single header file.' ) 191parser .add_argument ('-v' ,'--verbose' ,action = 'store_true' ,help = 'Show verbose output.' ) 192parser .add_argument (dest = 'header_paths' ,metavar = 'HEADER_FILE' ,nargs = '+' ,help = 'Input header file.' ) 193 194return parser 195 196#-------------------------------------------------------------------------------------------------------------------------------------------------------------- 197 198def parse_arguments (): 199parser = create_argument_parser () 200args = parser .parse_args () 201 202if args .verbose : 203logging .getLogger ().setLevel (logging .INFO ) 204else : 205logging .getLogger ().setLevel (logging .ERROR ) 206 207return args 208 209#-------------------------------------------------------------------------------------------------------------------------------------------------------------- 210 211def make_header (args ): 212prefix = HeaderPrefix (os .path .basename (args .output_path ) ) 213header = SingleHeader () 214 215for header_path in args .header_paths : 216header .append (header_path ) 217 218return str (prefix )+ str (header ) 219 220#-------------------------------------------------------------------------------------------------------------------------------------------------------------- 221 222def make_dir (path ): 223try : 224if not os .path .exists (path ): 225os .makedirs (path ) 226except os .error : 227pass 228except : 229raise 230 231#-------------------------------------------------------------------------------------------------------------------------------------------------------------- 232 233def write_header (args ,content ): 234path = os .path .realpath (args .output_path ) 235 236logging .info ('Writing \"' + path + '\"...' ) 237 238make_dir (os .path .dirname (path ) ) 239 240try : 241f = open (path ,'w' ) 242except : 243raise RuntimeError ('Failed to open file \"' + path + '\" for write!' ) 244 245f .write (content ) 246 247#-------------------------------------------------------------------------------------------------------------------------------------------------------------- 248 249if __name__ == '__main__' : 250result = - 1 251 252try : 253if sys .getdefaultencoding ().lower ()== 'ascii' : 254reload (sys ) 255sys .setdefaultencoding ('utf-8' ) 256 257args = parse_arguments () 258header = make_header (args ) 259 260write_header (args ,header ) 261 262result = 0 263 264except (KeyboardInterrupt ,SystemExit ): 265pass 266except : 267raise 268 269sys .exit (result ) 270 271#--------------------------------------------------------------------------------------------------------------------------------------------------------------