Files
build-python/build.py
2025-11-02 12:34:25 -03:00

272 lines
8.1 KiB
Python

#!/usr/bin/env python3
import os
import sys
import subprocess
import platform
from pathlib import Path
def clear_screen():
os.system('cls' if os.name == 'nt' else 'clear')
def print_header():
print("=" * 60)
print(" PYINSTALLER AUTOMATION TOOL")
print("=" * 60)
print()
def get_script_path():
while True:
script_path = input("Enter the full path to the Python script: ").strip()
script_path = script_path.strip('"\'')
if not script_path:
print("Path cannot be empty!")
continue
script_path = Path(script_path)
if not script_path.exists():
print("File not found!")
continue
if script_path.suffix.lower() != '.py':
print("File must have .py extension!")
continue
return script_path
def select_mode():
print("\nCOMPILATION MODE:")
print("1. One-file (single file)")
print("2. One-directory (folder with dependencies)")
while True:
choice = input("\nChoose mode (1-2): ").strip()
if choice == '1':
return True
elif choice == '2':
return False
print("Invalid option! Choose 1 or 2.")
def select_console():
print("\nEXECUTION MODE:")
print("1. With console (default)")
print("2. Without console (GUI/windowed)")
while True:
choice = input("\nChoose mode (1-2): ").strip()
if choice == '1':
return False
elif choice == '2':
return True
print("Invalid option! Choose 1 or 2.")
def select_optimization():
print("\nOPTIMIZATION:")
print("1. No optimization (default)")
print("2. Basic optimization (-O)")
print("3. Maximum optimization (-OO)")
optimizations = {'1': None, '2': '-O', '3': '-OO'}
while True:
choice = input("\nChoose optimization (1-3): ").strip()
if choice in optimizations:
return optimizations[choice]
print("Invalid option! Choose 1-3.")
def select_icon():
print("\nCUSTOM ICON:")
print("1. No custom icon")
print("2. Use custom icon")
while True:
choice = input("\nChoose option (1-2): ").strip()
if choice == '1':
return None
elif choice == '2':
icon_path = input("Enter path to .ico (Windows) or .png (Linux/Mac) file: ").strip()
icon_path = icon_path.strip('"\'')
if Path(icon_path).exists():
return icon_path
else:
print("Icon file not found!")
continue
print("Invalid option! Choose 1 or 2.")
def select_additional_files():
print("\nADDITIONAL FILES:")
print("1. Do not add files")
print("2. Add files/directories")
while True:
choice = input("\nChoose option (1-2): ").strip()
if choice == '1':
return []
elif choice == '2':
files = []
while True:
file_path = input("Enter file/directory path (or Enter to finish): ").strip()
if not file_path:
break
file_path = file_path.strip('"\'')
if Path(file_path).exists():
files.append(file_path)
print(f"File added: {file_path}")
else:
print("File not found!")
return files
print("Invalid option! Choose 1 or 2.")
def select_upx():
print("\nUPX COMPRESSION:")
print("1. Enable UPX compression (smaller files)")
print("2. Disable UPX compression")
while True:
choice = input("\nChoose option (1-2): ").strip()
if choice == '1':
return False
elif choice == '2':
return True
print("Invalid option! Choose 1 or 2.")
def build_command(script_path, onefile, windowed, optimization, icon, additional_files, noupx):
cmd = ['pyinstaller']
if onefile:
cmd.append('--onefile')
else:
cmd.append('--onedir')
if windowed:
cmd.append('--windowed')
if icon:
cmd.extend(['--icon', icon])
if optimization:
cmd.extend(['--python-option', optimization])
if noupx:
cmd.append('--noupx')
for file in additional_files:
if os.path.isdir(file):
cmd.extend(['--add-data', f'{file}{os.pathsep}{file}'])
else:
cmd.extend(['--add-data', f'{file}{os.pathsep}.'])
exe_name = script_path.stem
cmd.extend(['--name', exe_name])
cmd.append(str(script_path))
return cmd
def run_pyinstaller(command):
print(f"\nExecuting: {' '.join(command)}")
print("\nCompiling... This may take a few minutes...")
print("-" * 60)
try:
result = subprocess.run(command, check=True, capture_output=True, text=True)
print("Compilation completed successfully!")
return True
except subprocess.CalledProcessError as e:
print(f"Error during compilation:")
if e.stderr:
print(f"Stderr: {e.stderr}")
if e.stdout:
print(f"Stdout: {e.stdout}")
return False
except FileNotFoundError:
print("PyInstaller not found! Make sure it is installed.")
print("Install with: pip install pyinstaller")
return False
def show_summary(script_path, onefile, windowed, optimization, icon, additional_files, output_dir, noupx):
clear_screen()
print_header()
print("COMPILATION SUMMARY:")
print(f"Script: {script_path}")
print(f"Mode: {'One-file' if onefile else 'One-directory'}")
print(f"Console: {'No' if windowed else 'Yes'}")
print(f"Optimization: {optimization or 'None'}")
print(f"Icon: {icon or 'Default'}")
print(f"UPX: {'Disabled' if noupx else 'Enabled'}")
print(f"Additional files: {len(additional_files)}")
print(f"Output directory: {output_dir}")
print("-" * 60)
def main():
clear_screen()
print_header()
try:
subprocess.run(['pyinstaller', '--version'], capture_output=True, check=True)
except (subprocess.CalledProcessError, FileNotFoundError):
print("PyInstaller not found!")
install = input("Do you want to install PyInstaller? (y/n): ").strip().lower()
if install == 'y':
subprocess.run([sys.executable, '-m', 'pip', 'install', 'pyinstaller'])
else:
print("Exiting...")
return
script_path = get_script_path()
onefile = select_mode()
windowed = select_console()
optimization = select_optimization()
icon = select_icon()
additional_files = select_additional_files()
noupx = select_upx()
output_dir = Path("dist")
show_summary(script_path, onefile, windowed, optimization, icon, additional_files, output_dir, noupx)
confirm = input("\nProceed with compilation? (y/n): ").strip().lower()
if confirm != 'y':
print("Compilation canceled!")
return
command = build_command(script_path, onefile, windowed, optimization, icon, additional_files, noupx)
success = run_pyinstaller(command)
if success:
print(f"\nCompilation completed!")
print(f"Executable generated in: {output_dir}")
if onefile:
exe_name = script_path.stem
if os.name == 'nt':
exe_name += '.exe'
exe_path = output_dir / exe_name
else:
exe_dir = output_dir / script_path.stem
exe_name = script_path.stem
if os.name == 'nt':
exe_name += '.exe'
exe_path = exe_dir / exe_name
print(f"File: {exe_path}")
if exe_path.exists():
print("✅ Executable successfully created!")
else:
print("⚠️ Executable might not have been created correctly.")
else:
print("\nCompilation failed! Check the errors above.")
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\nProgram interrupted by user!")
except Exception as e:
print(f"Unexpected error: {e}")