#!/usr/bin/env python3 # Copyright © Advanced Micro Devices, Inc., or its affiliates. # SPDX-License-Identifier: MIT """ Script to copy external header files with nested headers inlined. Since this is intended for run time compilation, HIP headers are skipped entirely. """ import sys import os import re from pathlib import Path def inline_includes(filepath, root_dir, processed=None, depth=0, max_depth=100): """Recursively inline #include directives.""" if processed is None: processed = set() # Prevent infinite recursion if depth > max_depth: raise RuntimeError(f"Include depth exceeded {max_depth}") # Normalize path filepath = os.path.normpath(filepath) if filepath in processed: return [] processed.add(filepath) result = [] try: with open(filepath, "r", encoding="utf-8", errors="ignore") as f: for line in f: # Check for #include directives match = re.match(r'^\s*#include\s+[<"]([^>"]+)[>"]', line) if match: include_file = match.group(1) # Skip HIP headers entirely - do not include them at all if include_file.startswith("hip/"): continue # Try to find the included file relative to root include_path = os.path.join(root_dir, include_file) if os.path.exists(include_path): # Add comment showing what's being inlined result.append(f"// BEGIN INLINED: {include_file}") # Recursively inline inlined_content = inline_includes( include_path, root_dir, processed, depth + 1, max_depth ) result.extend(inlined_content) result.append(f"// END INLINED: {include_file}") else: # Keep the include if file not found (might be a system header) result.append(line.rstrip()) else: # Keep non-include lines as-is result.append(line.rstrip()) except Exception as e: print(f"Error processing {filepath}: {e}", file=sys.stderr) raise return result def main(): if len(sys.argv) != 4: print( "Usage: InlineHeader.py ", file=sys.stderr, ) sys.exit(1) source_file = sys.argv[1] root_dir = sys.argv[2] output_file = sys.argv[3] if not os.path.exists(source_file): print(f"Error: Source file not found: {source_file}", file=sys.stderr) sys.exit(1) if not os.path.exists(root_dir): print(f"Error: Root directory not found: {root_dir}", file=sys.stderr) sys.exit(1) # Generate guard name from output filename guard_name = Path(output_file).stem.upper().replace(".", "_") + "_H" try: content_lines = inline_includes(source_file, root_dir) # Write output with header guards with open(output_file, "w", encoding="utf-8") as f: f.write(f"#ifndef {guard_name}\n") f.write(f"#define {guard_name}\n\n") f.write("\n".join(content_lines)) f.write(f"\n\n#endif // {guard_name}\n") print(f"Successfully created {output_file}") except Exception as e: print(f"Error: {e}", file=sys.stderr) sys.exit(1) if __name__ == "__main__": main()