From c9ad3cf4c53bfcd77543e4101b5df06fa735a911 Mon Sep 17 00:00:00 2001 From: Mr Lima Date: Sun, 2 Nov 2025 12:34:25 -0300 Subject: [PATCH] Build Tool --- build.py | 272 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100644 build.py diff --git a/build.py b/build.py new file mode 100644 index 0000000..695bdab --- /dev/null +++ b/build.py @@ -0,0 +1,272 @@ +#!/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}") \ No newline at end of file