#!/usr/bin/env python3 """ Fix wrong export header includes by finding correct target names from CMakeLists.txt """ import os import re import subprocess from pathlib import Path # Mapping von bekannten falschen Includes zu korrekten Target-Namen basierend auf CMakeLists.txt Analyse KNOWN_MAPPINGS = { # Lts/Common/LtsWidgets 'Lts/Common/LtsWidgets': 'ltswidgets', # Lts/Common/LtsSession 'Lts/Common/LtsSession': 'ltssessiondata', # Lts/Common/LtsUtils/LtsUtilsSettings 'Lts/Common/LtsUtils/LtsUtilsSettings': 'ltsutilssettings', # Lts/Common/LtsCoordTrans 'Lts/Common/LtsCoordTrans': 'ltscoordtrans', # Lts/DDS/QosProfile 'Lts/DDS/QosProfile': 'qosprofile', # Lts/DDS/FTS 'Lts/DDS/FTS': 'ddsfts', # Lts/Services/AreaEffectSimulation 'Lts/Services/AreaEffectSimulation': 'svcaessimulation', # Lts/Services/CentralEffectSimulation 'Lts/Services/CentralEffectSimulation': 'aescore', # Lts/Proxies/Buildings/BuildingControlUnit 'Lts/Proxies/Buildings/BuildingControlUnit': 'buildingcontrolunit', # Lts/Plugins/SituationMapPlugin 'Lts/Plugins/SituationMapPlugin': 'situationmapplugin', # Z/src/WMS_Interface 'Z/src/WMS_Interface': 'wmsinterface', } def find_target_in_cmake(file_path, base_dir): """Search CMakeLists.txt files to find the target name for a given source file""" file_dir = Path(file_path).parent rel_path = Path(file_path).relative_to(base_dir) rel_dir = str(rel_path.parent) # Try to match directory to known mappings for dir_pattern, target_name in KNOWN_MAPPINGS.items(): if rel_dir.startswith(dir_pattern) or dir_pattern in rel_dir: return target_name # Search for CMakeLists.txt in the file's directory or parents cmake_file = file_dir / "CMakeLists.txt" if cmake_file.exists(): with open(cmake_file, 'r') as f: content = f.read() # Look for NGL_ADD_LIBRARY or NGL_ADD_LIBRARY2 matches = re.findall(r'NGL_ADD_LIBRARY[2]?\s*\([^)]+\s+(\w+)\s+(?:SHARED|MODULE|STATIC)', content) if matches: return matches[0].lower() matches = re.findall(r'NGL_ADD_LIBRARY\s*\(\w+\s+\w+\s+\w+\s+(\w+)\s+SHARED', content) if matches: return matches[0].lower() # Search parent directories for parent in file_dir.parents: if parent == base_dir.parent: break cmake_file = parent / "CMakeLists.txt" if cmake_file.exists(): with open(cmake_file, 'r') as f: content = f.read() matches = re.findall(r'NGL_ADD_LIBRARY[2]?\s*\([^)]+\s+(\w+)\s+(?:SHARED|MODULE|STATIC)', content) if matches: return matches[0].lower() return None def file_uses_export_macros(file_path): """Check if file uses any export macros""" with open(file_path, 'r') as f: content = f.read() patterns = [ r'\b\w+_EXPORT\b', r'\b\w+_EXPORTS\b', ] for pattern in patterns: if re.search(pattern, content): return True return False def fix_file(file_path, correct_export_header): """Fix the export header include in a file""" with open(file_path, 'r') as f: content = f.read() # Remove wrong includes wrong_patterns = [ r'#include\s+"s_export\.h"[ \t]*\n', r'#include\s+"n_export\.h"[ \t]*\n', r'#include\s+"a_export\.h"[ \t]*\n', r'#include\s+"z_export\.h"[ \t]*\n', r'#include\s+"ws_export\.h"[ \t]*\n', r'#include\s+"aar_export\.h"[ \t]*\n', ] for pattern in wrong_patterns: content = re.sub(pattern, '', content) # Add correct include if needed if correct_export_header: if '#pragma once' in content: content = re.sub( r'(#pragma once\s*\n)', f'\\1#include "{correct_export_header}"\n', content, count=1 ) else: match = re.match(r'(/\*.*?\*/\s*\n)?(#.*\n)*', content, re.DOTALL) if match: insert_pos = match.end() content = content[:insert_pos] + f'#include "{correct_export_header}"\n' + content[insert_pos:] with open(file_path, 'w') as f: f.write(content) def main(): base_dir = Path("/home/torsten/swy/sandbox/qt-migration-legatus/qt6-after/qt6-migrated-legatus").resolve() os.chdir(base_dir) wrong_includes = ['s_export.h', 'n_export.h', 'a_export.h', 'z_export.h'] files_to_fix = [] for wrong_include in wrong_includes: result = subprocess.run( ['grep', '-rl', f'"{wrong_include}"', '.'], capture_output=True, text=True ) for line in result.stdout.strip().split('\n'): if line and 'external/' not in line: files_to_fix.append(base_dir / line.lstrip('./')) print(f"Found {len(files_to_fix)} files with wrong export header includes\n") fixed_count = 0 removed_count = 0 skipped_count = 0 for file_path in files_to_fix: if not file_path.exists(): continue rel_path = file_path.relative_to(base_dir) print(f"Processing: {rel_path}") target = find_target_in_cmake(file_path, base_dir) if target: correct_header = f"{target}_export.h" uses_macros = file_uses_export_macros(file_path) if uses_macros: fix_file(file_path, correct_header) print(f" ✓ Fixed to {correct_header}") fixed_count += 1 else: fix_file(file_path, None) print(f" ✓ Removed include (no macros)") removed_count += 1 else: uses_macros = file_uses_export_macros(file_path) if uses_macros: print(f" ⚠ Skipped: Cannot determine target, but file uses export macros") skipped_count += 1 else: fix_file(file_path, None) print(f" ✓ Removed include (no macros, no target)") removed_count += 1 print(f"\n=== Summary ===") print(f"Fixed: {fixed_count}") print(f"Removed: {removed_count}") print(f"Skipped: {skipped_count}") if __name__ == '__main__': main()