#!/usr/bin/env python3 """ PyInstaller build script for drone simulation executables. Creates standalone executables that include PyBullet and dependencies. Usage: python build_exe.py # Build standalone_simulation python build_exe.py simulation_host # Build simulation_host python build_exe.py standalone # Build standalone_simulation python build_exe.py all # Build all """ import argparse import os import platform import sys from pathlib import Path try: import PyInstaller.__main__ import pybullet_data except ImportError as e: print(f"Missing dependency: {e}") print("Install with: pip install pyinstaller pybullet") sys.exit(1) def get_pybullet_data_path() -> str: return pybullet_data.getDataPath() def build_executable(source_name: str, output_name: str, console: bool = True): """Build a single executable.""" script_dir = Path(__file__).parent source_file = script_dir / source_name if not source_file.exists(): print(f"Error: {source_file} not found!") return False print(f"\nBuilding: {source_name} -> {output_name}") print("-" * 40) system = platform.system().lower() pybullet_path = get_pybullet_data_path() if system == 'windows': separator = ';' else: separator = ':' data_spec = f"{pybullet_path}{separator}pybullet_data" build_args = [ str(source_file), '--onefile', '--clean', f'--name={output_name}', f'--add-data={data_spec}', ] if console: build_args.append('--console') else: if system in ['windows', 'darwin']: build_args.append('--windowed') else: build_args.append('--console') try: PyInstaller.__main__.run(build_args) dist_dir = script_dir / "dist" if system == 'windows': exe_path = dist_dir / f"{output_name}.exe" elif system == 'darwin' and not console: exe_path = dist_dir / f"{output_name}.app" else: exe_path = dist_dir / output_name print(f" Created: {exe_path}") return True except Exception as e: print(f" Build failed: {e}") return False def main(): parser = argparse.ArgumentParser(description='Build simulation executables') parser.add_argument( 'target', nargs='?', default='standalone', choices=['standalone', 'simulation_host', 'all'], help='What to build (default: standalone)' ) args = parser.parse_args() print("=" * 60) print(" DRONE SIMULATION - BUILD EXECUTABLES") print("=" * 60) print(f"Platform: {platform.system()}") print(f"PyBullet data: {get_pybullet_data_path()}") success = True if args.target in ['standalone', 'all']: success &= build_executable( 'standalone_simulation.py', 'drone_simulation', console=False ) if args.target in ['simulation_host', 'all']: success &= build_executable( 'simulation_host.py', 'simulation_host', console=True ) print() print("=" * 60) if success: print(" BUILD COMPLETE!") print(" Executables in: dist/") else: print(" BUILD FAILED!") sys.exit(1) print("=" * 60) if __name__ == '__main__': main()