#!/usr/bin/env python3 """ Fix ALL export header includes in the migrated codebase. Converts paths like: #include #include To: #include """ import os import re import sys from pathlib import Path def find_export_headers(base_path): """Find all _export.h files and extract their base names.""" export_headers = {} for root, dirs, files in os.walk(base_path): for file in files: if file.endswith('_export.h'): export_headers[file] = os.path.join(root, file) return export_headers def fix_export_includes(file_path, export_header_names): """Fix export header includes in a file.""" try: with open(file_path, 'r', encoding='utf-8', errors='ignore') as f: content = f.read() except Exception as e: print(f"Error reading {file_path}: {e}") return False original_content = content fixed_count = 0 # Pattern: #include or #include "path/to/header_export.h" # Match any path that ends with _export.h pattern = r'#include\s*[<"]([^>"]*?)([a-zA-Z0-9_]+_export\.h)[>"]' def replace_include(match): nonlocal fixed_count full_path = match.group(1) + match.group(2) header_name = match.group(2) # Check if this is an export header if header_name in export_header_names: fixed_count += 1 # Return with same quote style quote = '<' if match.group(0).strip().startswith('#include <') else '"' close_quote = '>' if quote == '<' else '"' return f'#include {quote}{header_name}{close_quote}' return match.group(0) content = re.sub(pattern, replace_include, content) if content != original_content: try: with open(file_path, 'w', encoding='utf-8') as f: f.write(content) return True except Exception as e: print(f"Error writing {file_path}: {e}") return False return False def main(): base_path = Path('/home/torsten/swy/sandbox/qt-migration-legatus/qt6-after/qt6-migrated-legatus') print("Finding all _export.h files...") export_headers = find_export_headers(base_path) export_header_names = set(export_headers.keys()) print(f"Found {len(export_headers)} export headers") # Find all C++ source and header files cpp_extensions = {'.h', '.hpp', '.cpp', '.cc', '.cxx', '.hxx'} files_to_check = [] print("Scanning source files...") for root, dirs, files in os.walk(base_path): # Skip build directories if 'build' in root or '.git' in root: continue for file in files: if Path(file).suffix.lower() in cpp_extensions: files_to_check.append(os.path.join(root, file)) print(f"Checking {len(files_to_check)} files...") fixed_files = [] total_fixes = 0 for file_path in files_to_check: if fix_export_includes(file_path, export_header_names): fixed_files.append(file_path) total_fixes += 1 if total_fixes <= 10: print(f" Fixed: {file_path}") print(f"\n{'='*70}") print(f"Export header include fix complete!") print(f" Files fixed: {total_fixes}") print(f"{'='*70}") if fixed_files: print("\nFirst 20 fixed files:") for f in fixed_files[:20]: print(f" - {f}") if len(fixed_files) > 20: print(f" ... and {len(fixed_files) - 20} more") if __name__ == '__main__': main()