123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- #
- # Copyright (c) Contributors to the Open 3D Engine Project.
- # For complete copyright and license terms please see the LICENSE at the root of this distribution.
- #
- # SPDX-License-Identifier: Apache-2.0 OR MIT
- #
- #
- import argparse
- import fnmatch
- import os
- import shutil
- import sys
- sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '../build'))
- import ci_build
- EXTENSIONS_OF_INTEREST = ('.c', '.cc', '.cpp', '.cxx', '.h', '.hpp', '.hxx', '.inl')
- EXCLUSIONS = (
- 'AZ_DECLARE_MODULE_CLASS(',
- 'REGISTER_QT_CLASS_DESC(',
- 'TEST(',
- 'TEST_F(',
- 'TEST_P(',
- 'INSTANTIATE_TEST_CASE_P(',
- 'INSTANTIATE_TYPED_TEST_CASE_P(',
- 'AZ_UNIT_TEST_HOOK(',
- 'IMPLEMENT_TEST_EXECUTABLE_MAIN(',
- 'BENCHMARK_REGISTER_F(',
- 'DllMain(',
- 'wWinMain(',
- 'AZ_DLL_EXPORT',
- 'CreatePluginInstance('
- )
- PATH_EXCLUSIONS = (
- '*\\Platform\\Android\\*',
- '*\\Platform\\Common\\*',
- '*\\Platform\\iOS\\*',
- '*\\Platform\\Linux\\*',
- '*\\Platform\\Mac\\*',
- 'Templates\\*',
- 'python\\*',
- 'build\\*',
- 'install\\*',
- 'Gems\\ImGui\\External\\ImGui\\*',
- '*_Traits_*.h',
- )
- def create_filelist(path):
- filelist = set()
- for input_file in path:
- if os.path.isdir(input_file):
- for dp, dn, filenames in os.walk(input_file):
- if 'build\\windows' in dp:
- continue
- for f in filenames:
- extension = os.path.splitext(f)[1]
- extension_lower = extension.lower()
- if extension_lower in EXTENSIONS_OF_INTEREST:
- normalized_file = os.path.normpath(os.path.join(dp, f))
- filelist.add(normalized_file)
- else:
- extension = os.path.splitext(input_file)[1]
- extension_lower = extension.lower()
- if extension_lower in EXTENSIONS_OF_INTEREST:
- normalized_file = os.path.normpath(os.path.join(os.getcwd(), input_file))
- filelist.add(normalized_file)
- else:
- print(f'Error, file {input_file} does not have an extension of interest')
- sys.exit(1)
- return filelist
- def is_excluded(file):
- for path_exclusion in PATH_EXCLUSIONS:
- if fnmatch.fnmatch(file, path_exclusion):
- return True
- with open(file, 'r') as file:
- contents = file.read()
- for exclusion_term in EXCLUSIONS:
- if exclusion_term in contents:
- return True
- return False
- def filter_from_processed(filelist, filter_file_path):
- filelist = set([f for f in filelist if not is_excluded(f)])
- if os.path.exists(filter_file_path):
- with open(filter_file_path, 'r') as filter_file:
- processed_files = [s.strip() for s in filter_file.readlines()]
- filelist -= set(processed_files)
- return filelist
- def cleanup_unused_compilation(path):
- # 1. Create a list of all h/cpp files (consider multiple extensions)
- filelist = create_filelist(path)
- # 2. Remove files from "processed" list. This is needed because the process is a bruteforce approach and
- # can take a while. If something is found in the middle, we want to be able to continue instead of
- # starting over. Removing the "unusued_compilation_processed.txt" will start over.
- filter_file_path = os.path.join(os.getcwd(), 'unusued_compilation_processed.txt')
- filelist = filter_from_processed(filelist, filter_file_path)
- sorted_filelist = sorted(filelist)
- # 3. For each file
- total_files = len(sorted_filelist)
- current_files = 1
- for file in sorted_filelist:
- print(f"[{current_files}/{total_files}] Trying {file}")
- # b. create backup
- shutil.copy(file, file + '.bak')
- # c. set the file contents as empty
- with open(file, 'w') as source_file:
- source_file.write('')
- # d. build
- ret = ci_build.build('build_config.json', 'Windows', 'profile')
- # e.1 if build succeeds, leave the file empty (leave backup)
- # e.2 if build fails, restore backup
- if ret != 0:
- shutil.copy(file + '.bak', file)
- print(f"\t[FAILED] restoring")
- else:
- print(f"\t[SUCCEED]")
- # f. delete backup
- os.remove(file + '.bak')
- # add file to processed-list
- with open(filter_file_path, 'a') as filter_file:
- filter_file.write(file)
- filter_file.write('\n')
- current_files += 1
- if __name__ == "__main__":
- parser = argparse.ArgumentParser(description='This script finds C++ files that do not affect compilation (and therefore can be potentially removed)',
- formatter_class=argparse.RawTextHelpFormatter)
- parser.add_argument('file_or_dir', type=str, nargs='+', default=os.getcwd(),
- help='list of files or directories to search within for files to consider')
- args = parser.parse_args()
- ret = cleanup_unused_compilation(args.file_or_dir)
- sys.exit(ret)
|