File size: 3,066 Bytes
197b66d
5f94b93
197b66d
 
 
b7df2fe
197b66d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b7df2fe
197b66d
 
 
 
a42743f
197b66d
5f94b93
197b66d
 
 
 
 
 
 
 
 
a42743f
197b66d
 
 
 
 
a42743f
 
 
 
 
 
 
b7df2fe
 
 
a42743f
b7df2fe
 
 
197b66d
 
 
 
 
b7df2fe
 
 
197b66d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b7df2fe
197b66d
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import os
import sys
import platform
import subprocess


def get_providers():
    """
    Scans the 'src/rotator_library/providers' directory to find all provider modules.
    Returns a list of hidden import arguments for PyInstaller.
    """
    hidden_imports = []
    # Get the absolute path to the directory containing this script
    script_dir = os.path.dirname(os.path.abspath(__file__))
    # Construct the path to the providers directory relative to this script's location
    providers_path = os.path.join(script_dir, "..", "rotator_library", "providers")

    if not os.path.isdir(providers_path):
        print(f"Error: Directory not found at '{os.path.abspath(providers_path)}'")
        return []

    for filename in os.listdir(providers_path):
        if filename.endswith("_provider.py") and filename != "__init__.py":
            module_name = f"rotator_library.providers.{filename[:-3]}"
            hidden_imports.append(f"--hidden-import={module_name}")
    return hidden_imports


def main():
    """
    Constructs and runs the PyInstaller command to build the executable.
    """
    # Base PyInstaller command with optimizations
    command = [
        sys.executable,
        "-m",
        "PyInstaller",
        "--onefile",
        "--name",
        "proxy_app",
        "--paths",
        "../",
        "--paths",
        ".",
        # Core imports
        "--hidden-import=rotator_library",
        "--hidden-import=tiktoken_ext.openai_public",
        "--hidden-import=tiktoken_ext",
        "--collect-data",
        "litellm",
        # Optimization: Exclude unused heavy modules
        "--exclude-module=matplotlib",
        "--exclude-module=IPython",
        "--exclude-module=jupyter",
        "--exclude-module=notebook",
        "--exclude-module=PIL.ImageTk",
        # Optimization: Enable UPX compression (if available)
        "--upx-dir=upx"
        if platform.system() != "Darwin"
        else "--noupx",  # macOS has issues with UPX
        # Optimization: Strip debug symbols (smaller binary)
        "--strip"
        if platform.system() != "Windows"
        else "--console",  # Windows gets clean console
    ]

    # Add hidden imports for providers
    provider_imports = get_providers()
    if not provider_imports:
        print(
            "Warning: No providers found. The build might not include any LLM providers."
        )
    command.extend(provider_imports)

    # Add the main script
    command.append("main.py")

    # Execute the command
    print(f"Running command: {' '.join(command)}")
    try:
        # Run PyInstaller from the script's directory to ensure relative paths are correct
        script_dir = os.path.dirname(os.path.abspath(__file__))
        subprocess.run(command, check=True, cwd=script_dir)
        print("Build successful!")
    except subprocess.CalledProcessError as e:
        print(f"Build failed with error: {e}")
    except FileNotFoundError:
        print("Error: PyInstaller is not installed or not in the system's PATH.")


if __name__ == "__main__":
    main()