244 lines
9.0 KiB
Python
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()) |