PLC_Generation/setup_compilation.py
2025-08-05 14:38:54 +04:00

244 lines
9.0 KiB
Python

#!/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())