135 lines
3.4 KiB
Python
135 lines
3.4 KiB
Python
#!/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()
|