#!/usr/bin/env python3 """ Standalone PLC Compilation Setup Script ======================================= This script provides easy compilation setup for different PLC projects. It uses the dynamic compilation manager to wipe existing files and create project-specific batch files and L5X copies. Usage Examples: # Setup compilation for different projects python setup_compilation.py --project MTN6_MCM01_UL1_UL3 python setup_compilation.py --project MTN6_MCM04_CHUTE_LOAD # Setup with custom L5X file python setup_compilation.py --project CustomProject --l5x-file "path/to/custom.L5X" # Just wipe existing files python setup_compilation.py --wipe-only # Quick setup for last generated project python setup_compilation.py --auto """ import sys import argparse from pathlib import Path import glob # Add L5X2ACD Compiler to path for compilation_manager import script_dir = Path(__file__).parent l5x2acd_dir = script_dir / "L5X2ACD Compiler" sys.path.append(str(l5x2acd_dir)) from compilation_manager import CompilationManager def find_latest_l5x_file() -> Path: """Find the most recently generated L5X file in the IO Tree output directory. Returns: Path to the latest L5X file Raises: FileNotFoundError: If no L5X files are found """ io_tree_output = script_dir / "IO Tree Configuration Generator" / "generated_projects" if not io_tree_output.exists(): raise FileNotFoundError(f"IO Tree output directory not found: {io_tree_output}") l5x_files = list(io_tree_output.glob("*.L5X")) if not l5x_files: raise FileNotFoundError(f"No L5X files found in {io_tree_output}") # Sort by modification time (most recent first) latest_l5x = max(l5x_files, key=lambda f: f.stat().st_mtime) return latest_l5x def extract_project_name_from_l5x(l5x_file: Path) -> str: """Extract project name from L5X filename. Args: l5x_file: Path to the L5X file Returns: Project name extracted from filename """ # Remove .L5X extension and return as project name return l5x_file.stem def main(): """Main entry point for standalone compilation setup.""" parser = argparse.ArgumentParser( description="Standalone PLC Compilation Setup", formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" Project Types Supported: MCM01 Projects: Unit Line Configuration - Example: MTN6_MCM01_UL1_UL3 - Features: Safety validation, unit line zones MCM04 Projects: Feeder Line Configuration - Example: MTN6_MCM04_CHUTE_LOAD - Features: Feeder optimization, chute control Custom Projects: Any other project type - Features: Basic compilation setup Examples: # Auto-detect latest project python setup_compilation.py --auto # Setup specific project (will look for matching L5X file) python setup_compilation.py --project MTN6_MCM01_UL1_UL3 # Setup with custom L5X file python setup_compilation.py --project MyProject --l5x-file "custom.L5X" # Just clean up compilation directory python setup_compilation.py --wipe-only # Setup with project-specific options python setup_compilation.py --project MTN6_MCM01_UL1_UL3 --enable-safety-validation """ ) # Main operation modes mode_group = parser.add_mutually_exclusive_group() mode_group.add_argument('--auto', action='store_true', help='Auto-detect the latest generated project and setup compilation') mode_group.add_argument('--wipe-only', action='store_true', help='Only wipe existing files, do not setup compilation') mode_group.add_argument('--project', '-p', help='Project name (e.g., MTN6_MCM01_UL1_UL3)') # File options parser.add_argument('--l5x-file', '-l', type=Path, help='Path to specific L5X file (auto-detected if not provided)') # Compilation options parser.add_argument('--enable-safety-validation', action='store_true', help='Enable safety validation for MCM01 projects') parser.add_argument('--enable-feeder-optimization', action='store_true', help='Enable feeder optimization for MCM04 projects') parser.add_argument('--no-wipe', action='store_true', help='Do not wipe existing files before setup') # Directory options parser.add_argument('--compilation-dir', type=Path, default=l5x2acd_dir, help='Compilation directory (default: L5X2ACD Compiler)') args = parser.parse_args() try: # Create compilation manager manager = CompilationManager(args.compilation_dir) # Handle wipe-only mode if args.wipe_only: print("๐Ÿงน Wiping compilation directory...") manager.wipe_compilation_files(preserve_core=True) print("โœ… Wipe completed.") return 0 # Handle auto mode if args.auto: print("๐Ÿ” Auto-detecting latest project...") try: latest_l5x = find_latest_l5x_file() project_name = extract_project_name_from_l5x(latest_l5x) l5x_file = latest_l5x print(f" Found: {project_name} ({latest_l5x.name})") except FileNotFoundError as e: print(f"โŒ Auto-detection failed: {e}") return 1 # Handle project mode elif args.project: project_name = args.project # Find L5X file for the project if args.l5x_file: l5x_file = args.l5x_file else: # Auto-detect L5X file for the project io_tree_output = script_dir / "IO Tree Configuration Generator" / "generated_projects" potential_files = list(io_tree_output.glob(f"{project_name}*.L5X")) if not potential_files: print(f"โŒ No L5X file found for project '{project_name}' in {io_tree_output}") available_files = list(io_tree_output.glob("*.L5X")) if available_files: print(f"Available L5X files: {[f.name for f in available_files]}") return 1 l5x_file = potential_files[0] if len(potential_files) > 1: print(f"โš ๏ธ Multiple L5X files found for project '{project_name}', using: {l5x_file.name}") else: print("โŒ ERROR: Must specify --auto, --project, or --wipe-only") parser.print_help() return 1 # Validate L5X file if not l5x_file.exists(): print(f"โŒ ERROR: L5X file not found: {l5x_file}") return 1 # Setup compilation options based on project type options = {} project_upper = project_name.upper() if "MCM01" in project_upper: options['enable_safety_validation'] = args.enable_safety_validation or True print(f"๐Ÿ”ง Detected MCM01 project type") elif "MCM04" in project_upper: options['enable_feeder_optimization'] = args.enable_feeder_optimization or True print(f"๐Ÿ”ง Detected MCM04 project type") else: options['enable_safety_validation'] = args.enable_safety_validation options['enable_feeder_optimization'] = args.enable_feeder_optimization print(f"๐Ÿ”ง Using custom project type") # Print setup summary print() print("๐Ÿ“‹ Compilation Setup Summary:") print(f" Project: {project_name}") print(f" L5X File: {l5x_file}") print(f" Compilation Dir: {args.compilation_dir}") print(f" Wipe Existing: {not args.no_wipe}") if options: print(f" Options: {options}") print() # Setup compilation result = manager.setup_compilation( source_l5x=l5x_file, project_name=project_name, compilation_options=options, wipe_existing=not args.no_wipe ) print("๐ŸŽ‰ Compilation setup completed successfully!") print() print("๐Ÿ“ Generated Files:") print(f" L5X File: {result['l5x_file']}") print(f" Batch File: {result['batch_file']}") print() print("๐ŸชŸ Ready for Windows compilation!") print(f" Run: {result['batch_file']}") print(f" Or double-click: {result['batch_file'].name}") return 0 except Exception as e: print(f"โŒ ERROR: {e}") import traceback traceback.print_exc() return 1 if __name__ == '__main__': sys.exit(main())