""" Build the Lightweight Bootstrapper ================================== This creates a small (~15-20MB) .exe that downloads Python + dependencies on first run. """ import os import shutil import PyInstaller.__main__ from pathlib import Path def build_bootstrapper(): project_root = Path(__file__).parent.absolute() dist_path = project_root / "dist" # Collect all app source files to bundle # These will be extracted and used when setting up app_source_files = [ ("src", "app_source/src"), ("assets", "app_source/assets"), # Include icon etc ("main.py", "app_source"), ("requirements.txt", "app_source"), ] add_data_args = [] for src, dst in app_source_files: src_path = project_root / src if src_path.exists(): add_data_args.extend(["--add-data", f"{src}{os.pathsep}{dst}"]) # Use absolute project root for copying shutil.copy2(project_root / "assets" / "icon.ico", project_root / "app_icon.ico") print("šŸš€ Building Lightweight Bootstrapper...") print("ā³ This creates a small .exe that downloads dependencies on first run.\n") PyInstaller.__main__.run([ "bootstrapper.py", "--name=WhisperVoice", "--onefile", "--noconsole", # Re-enabled! Error handling in bootstrapper is ready. "--clean", "--icon=app_icon.ico", # Simplified path at root *add_data_args, ]) exe_path = dist_path / "WhisperVoice.exe" if exe_path.exists(): size_mb = exe_path.stat().st_size / (1024 * 1024) print("\n" + "="*60) print("āœ… BOOTSTRAPPER BUILD COMPLETE!") print("="*60) print(f"\nšŸ“ Output: {exe_path}") print(f"šŸ“¦ Size: {size_mb:.1f} MB") print("\nšŸ“‹ How it works:") print(" 1. User runs WhisperVoice.exe") print(" 2. First run: Downloads Python + packages (~2-3GB)") print(" 3. Subsequent runs: Launches instantly") print("\nšŸ’” The 'runtime/' folder will be created next to the .exe") else: print("\nāŒ Build failed. Check the output above for errors.") if __name__ == "__main__": os.chdir(Path(__file__).parent) build_bootstrapper()