tornavis/tools/check_source/check_header_duplicate.py

91 lines
2.1 KiB
Python
Executable File

#!/usr/bin/env python3
# SPDX-FileCopyrightText: 2023 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later
"""
Run this script to check if headers are included multiple times.
python3 check_header_duplicate.py ../../
Now build the code to find duplicate errors, resolve them manually.
Then restore the headers to their original state:
python3 check_header_duplicate.py --restore ../../
"""
# Use GCC's __INCLUDE_LEVEL__ to find direct duplicate includes
UUID = 0
def source_filepath_guard(filepath):
global UUID
footer = """
#if __INCLUDE_LEVEL__ == 1
# ifdef _DOUBLEHEADERGUARD_%d
# error "duplicate header!"
# endif
#endif
#if __INCLUDE_LEVEL__ == 1
# define _DOUBLEHEADERGUARD_%d
#endif
""" % (UUID, UUID)
UUID += 1
with open(filepath, 'a', encoding='utf-8') as f:
f.write(footer)
def source_filepath_restore(filepath):
import os
os.system("git co %s" % filepath)
def scan_source_recursive(dirpath, is_restore):
import os
from os.path import join, splitext
# ensure git working dir is ok
os.chdir(dirpath)
def source_list(path, filename_check=None):
for dirpath, dirnames, filenames in os.walk(path):
# skip '.git'
dirnames[:] = [d for d in dirnames if not d.startswith(".")]
for filename in filenames:
filepath = join(dirpath, filename)
if filename_check is None or filename_check(filepath):
yield filepath
def is_source(filename):
ext = splitext(filename)[1]
return (ext in {".hpp", ".hxx", ".h", ".hh"})
def is_ignore(filename):
pass
for filepath in sorted(source_list(dirpath, is_source)):
print("file:", filepath)
if is_ignore(filepath):
continue
if is_restore:
source_filepath_restore(filepath)
else:
source_filepath_guard(filepath)
def main():
import sys
is_restore = ("--restore" in sys.argv[1:])
scan_source_recursive(sys.argv[-1], is_restore)
if __name__ == "__main__":
main()